diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ad71d7c0cf..ff30ae9683 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,7 +1,7 @@ -/data/ @christinerose +/data/changelog/ @sabine /data/pages/governance.md @avsm /data/pages/privacy_policy.md @avsm /data/pages/carbon_footprint.md @avsm /data/tutorials/platform/op_00_principles.md @avsm /data/tutorials/platform/op_01_users.md @avsm -/data/tutorials/guides/op_02_roadmap.md @avsm \ No newline at end of file +/data/tutorials/guides/op_02_roadmap.md @avsm diff --git a/.github/PULL_REQUEST_TEMPLATE/cookbook_pr_template.md b/.github/PULL_REQUEST_TEMPLATE/cookbook_pr_template.md new file mode 100644 index 0000000000..4e73e1f822 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/cookbook_pr_template.md @@ -0,0 +1,16 @@ +#### Checklist +Ensure the following are addressed before submitting your PR: + +1. **Real-World Usefulness**: + - [ ] Does the task address a practical need in real-world application development? + +2. **Code Quality**: + - [ ] Is the code production-ready, safe, and free of potential security issues? + - [ ] Does the code avoid uncaught exceptions or other potential pitfalls? + +3. **Standard Library and Packages**: + - [ ] For tasks using the Standard Library: Does this recipe provide value beyond what an LLM could easily generate? + - [ ] For tasks using a package: Does this recipe implicitly recommend the package for production use? + +4. **Recipe Redundancy**: + - [ ] Does this recipe duplicate an existing task? If so, does it add value by showing differences between packages or approaches? \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 0000000000..3b9a8ec330 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,4 @@ +Please go to the `Preview` tab and select the appropriate sub-template: + +* [Other PR](?expand=1&template=other_pr_template.md) +* [OCaml Cookbook Contribution](?expand=1&template=cookbook_pr_template.md) diff --git a/.github/other_pr_template.md b/.github/other_pr_template.md new file mode 100644 index 0000000000..3c33591eaa --- /dev/null +++ b/.github/other_pr_template.md @@ -0,0 +1,4 @@ +## Checklist + +* [ ] Please format your code using `make fmt` +* [ ] If addressing an open issue, please link to it by writing "Resolves #1234" (use the relevant issue number) \ No newline at end of file diff --git a/.gitignore b/.gitignore index d8bb9526df..486f5dd41c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ _opam/ # Files that people sometimes accidentally include in their PRs *:OECustomProperty + +# TailwindCSS opam file, which appears to be generated by the build +tailwindcss.opam diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 63359e06f6..5a915b87c1 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -4,4 +4,4 @@ This project has adopted the [OCaml Code of Conduct](https://github.com/ocaml/co # Enforcement -This project follows the OCaml Code of Conduct [enforcement policy](https://github.com/ocaml/code-of-conduct/blob/main/CODE_OF_CONDUCT.md#enforcement). \ No newline at end of file +This project follows the OCaml Code of Conduct [enforcement policy](https://github.com/ocaml/code-of-conduct/blob/main/CODE_OF_CONDUCT.md#enforcement). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7f690004fa..d750b412f4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,7 +22,8 @@ We've provided a list of community-driven content below. When adding content to - [The OCaml Planet](#ocaml-planet) - [Job Board](#content-job) - [Success Stories](#content-success-story) -- [Academic and Industrial Users](#content-user) +- [Academic Users](#content-academic-user) +- [Industrial Users](#content-industrial-user) - [OCaml Books](#content-book) - [OCaml Cookbook Recipes](#content-cookbook) - [Recurring Events](#content-recurring-event) @@ -104,13 +105,50 @@ The success stories should be structured in the following way: You can read [Ahref's Success Story](https://ocaml.org/success-stories/peta-byte-scale-web-crawler) for a good example. -### Add an Academic or Industrial User +### Add an Academic User -> Contribute to the [Academic Users](https://ocaml.org/academic-users) and [Industrial Users](https://ocaml.org/industrial-users). +> Contribute to the [Academic Users](https://ocaml.org/academic-users). -Add a new industrial user by creating a new Markdown file in [data/industrial_users/](data/industrial_users/). For instance: [cryptosense.md](data/industrial_users/cryptosense.md). +You can add a new academic user by creating a new Markdown file in [data/academic_institutions/](data/academic_institutions). When submitting an academic institution to our webpage, please structure the data as follows: -You can add a new academic user by creating a new Markdown file in [data/academic_institutions/](data/academic_institutions). For instance: [cornell.md](data/academic_institutions/cornell.md). +Information about the institution +- **`name`**: The full name of the academic institution. +- **`description`**: A brief overview of the institution, including its background and key details. +- **`url`**: The official website of the institution. +- **`logo`**: A link to the institution’s logo image. +- **`continent`**: The continent where the institution is located. + +A list of courses available at the institution. Each course entry must include: +- **`name`**: The full name of the course. +- **`acronym`**: The course code or identifier. +- **`url`**: A direct link to the course webpage. + +Location +- **`lat`**: The latitude of the institution’s location. +- **`long`**: The longitude of the institution’s location. + +For instance: [cornell.md](data/academic_institutions/cornell.md). + +### Add an Industrial User + +> Contribute to the [Industrial Users](https://ocaml.org/industrial-users). + +Add a new industrial user by creating a new Markdown file in [data/industrial_users/](data/industrial_users/). When submitting an industrial user to our webpage, please structure the data as follows: + +Information about the organization +- **`name`**: The full name of the organization. +- **`description`**: A brief overview of the organization, including its mission and key details. +- **`logo`**: A link to the organization’s logo image. +- **`url`**: The official website of the organization. + +Locations +- A list of countries where the organization operates. + +Additional Information +- **`consortium`**: Indicates whether the organization is part of a consortium (`true` or `false`). +- **`featured`**: Indicates whether the organization is highlighted as a featured entity (`true` or `false`). + +For instance: [cryptosense.md](data/industrial_users/cryptosense.md). ### Add a Book @@ -124,10 +162,10 @@ The OCaml Cookbook is a place where OCaml developers share how to solve common tasks in OCaml using packages from the OCaml ecosystem. Here are the steps to contribute a recipe for an existing task: -* Find the task in the [data/cookbook/tasks.yml](data/cookbook/tasks.yml) file. -* Go to the task folder inside [data/cookbook/](data/cookbook/) that has the +- Find the task in the [data/cookbook/tasks.yml](data/cookbook/tasks.yml) file. +- Go to the task folder inside [data/cookbook/](data/cookbook/) that has the same name as the task's `slug`. -* Create a `.ml` file containing the recipe and a YAML header with metadata about +- Create a `.ml` file containing the recipe and a YAML header with metadata about the recipe. If the recipe does not fit into any existing task, you also need to create a @@ -138,7 +176,7 @@ located under a relevant `category:` field. Finally, it is also possible to create and organise groups of tasks by creating new categories. Categories are recursive and may have subcategories, which are full categories too. A task listed in -[data/cookbook/tasks.yml](data/cookbook/tasks.yml) may have no recipes yet. On the +[data/cookbook/tasks.yml](data/cookbook/tasks.yml) may have no recipes yet. On the other hand, it is not allowed to have a task folder in [data/cookbook/](data/cookbook/) that does not correspond to a task from the [data/cookbook/tasks.yml](data/cookbook/tasks.yml) file because it triggers a @@ -147,14 +185,27 @@ compilation error. Each recipe is a way to perform a task using a combination of open-source libraries. -#### OCaml Cookbook Recipe Review Checklist +#### Guidelines for New OCaml Cookbook Recipes + +When contributing new recipes to the OCaml Cookbook, please adhere to the following: + +1. **Task Selection**: + - Focus on practical, reusable tasks relevant to a wide audience. + - Ensure the task demonstrates idiomatic OCaml usage. + - Avoid tasks that are overly trivial or highly specific to niche cases. + +2. **Code Standards**: + - Write clear, idiomatic OCaml code. + - Ensure the code compiles without errors or warnings. + - Use standard OCaml libraries and tools wherever possible. -Checklist for reviewing OCaml cookbook submissions: +3. **Evaluation Criteria**: + - Does the recipe address a useful real-world task? + - Is the code ready for production use? + - If using a package, does it implicitly recommend the package for production? + - Avoid duplicating existing recipes unless demonstrating package differences. -1. does this recipe implement the task it's assigned to? -2. if this recipe is creating a new task: (1) is the new task substantially different from existing tasks, (2) there is no existing task that this recipe solves, (3) is the new task description very clear on what the task is (be specific!) -3. is the code explained sufficiently without overexplaining (be short and focus on what matters)? -4. is the code such that you would put it into production? I.e. are the libraries used stable enough and is the code readable? +Following these guidelines will help us maintain a high-quality and consistent OCaml Cookbook. ### Add A Recurring Event @@ -181,7 +232,7 @@ The Changelog covers developments across: #### Purpose and Audience -The primary audience for the Changelog is OCaml users. Content should focus on changes, updates, and news that directly impact users of OCaml and its ecosystem. +The primary audience for the Changelog is OCaml users. Content should focus on changes, updates, and news that directly impact users of OCaml and its ecosystem. Good candidates for Changelog posts include: diff --git a/DOCUMENTATION_WRITING.md b/DOCUMENTATION_WRITING.md index 7affab9170..2cd21973ef 100644 --- a/DOCUMENTATION_WRITING.md +++ b/DOCUMENTATION_WRITING.md @@ -1,8 +1,8 @@ # How to Write Documentation -This document explains how to write documentation such as tutorials, guides, or recommendations to be hosted in OCaml.org. It's also meant to be used as a style guide to ensure consistency in things like grammar, formatting, capitalisation, and spelling across all OCaml.org documentation. +This document explains how to write documentation such as tutorials, guides, or recommendations to be hosted in OCaml.org. It's also meant to be used as a style guide to ensure consistency in things like grammar, formatting, capitalisation, and spelling across all OCaml.org documentation. -Apply the [*Spiral Learning*](https://en.wikipedia.org/wiki/Spiral_approach) approach in tutorials. This teaching method first creates a solid foundation of a topic. By starting with an overview, it gives the reader the context and general information. Subsequent sections and tutorials review the important foundational information and expands, going into more detail and giving examples. +Apply the [*Spiral Learning*](https://en.wikipedia.org/wiki/Spiral_approach) approach in tutorials. This teaching method first creates a solid foundation of a topic. By starting with an overview, it gives the reader the context and general information. Subsequent sections and tutorials review the important foundational information and expands, going into more detail and giving examples. ## Materials @@ -16,26 +16,28 @@ Apply the [*Spiral Learning*](https://en.wikipedia.org/wiki/Spiral_approach) app ## Audience -Anytime one contributes to the OCaml.org documentation, it's important to keep the target audience in mind. For example, if writing a tutorial for programmers new to OCaml, you want to ensure the examples are simple and straighforward so as not to overwhelm them with too much detail while starting their learning journey. For more advanced users, adjust the tone and examples accordingly. +Anytime one contributes to the OCaml.org documentation, it's important to keep the target audience in mind. For example, if writing a tutorial for programmers new to OCaml, you want to ensure the examples are simple and straighforward so as not to overwhelm them with too much detail while starting their learning journey. For more advanced users, adjust the tone and examples accordingly. **Our audience:** -* Self-directed learners without a tutor -* Already know some programming basics (one other programming language) -* Likely a majority of consumers of libraries, hopefully some authors or people who turn into it -* English level B2 ideally +- Self-directed learners without a tutor +- Already know some programming basics (one other programming language) +- Likely a majority of consumers of libraries, hopefully some authors or people who turn into it +- English level B2 ideally **Not our audience:** -* University students -* New to programming. We do not teach programming basics. +- University students +- New to programming. We do not teach programming basics. ## Goals + Especially since the release of OCaml 5.0 with Multicore support, perhaps our biggest goal is to increase the adoption of OCaml. In order to reach this goal, it's essential to have current, consistent, and comprehensive documentation. 1. Enable people to use OCaml for real projects / at the job / side projects 1. Get people who want to build and contribute to the ecosystem up to speed and building something good quickly 1. **Oddly Specific**: Enable people to do Advent of Code in OCaml. -## Our Key Values / Constraints: +## Our Key Values / Constraints + - **Goals and Prerequisites**. Each tutorial begins with its objectives, so that people know what they will learn about.``` - **Avoid Overwhelming Choices**. Tutorials should guide learners on a straightforward path, avoiding multiple options. This makes the learning process smoother. Detailed choices can be included in additional references and guides. - **Highlight Important Computer Science Terms**. Use italics for well-known terms, providing a visual hint that these are important concepts. Linking to Wikipedia for further explanation is an option. @@ -47,32 +49,31 @@ Especially since the release of OCaml 5.0 with Multicore support, perhaps our bi ## Common Phrases - "Binding a value to a name" = declaring a variable -- `'a` is a type parameter called "alpha." It is not a _type variable_ (because the term _variable_ is a forbidden word). +- `'a` is a type parameter called "alpha." It is not a *type variable* (because the term *variable* is a forbidden word). - Pass a function as a value to another function as a parameter - not a "function value" - ## Things to Avoid -1. Don't use the same letter for different things, i.e., when talking about a type parameter `'a`, don't have a name `a` nearby. In fact, since `a` can easily be confused with `'a` (alpha), start with `f` when using letters as parameters. +1. Don't use the same letter for different things, i.e., when talking about a type parameter `'a`, don't have a name `a` nearby. In fact, since `a` can easily be confused with `'a` (alpha), start with `f` when using letters as parameters. 1. Never use the term "variable," instead a. Names and values (binding = a value is bound to a name) b. Type parameter 1. Use “parameter” and “argument” appropriately. Parameters occur in function declarations. Arguments are values that functions are applied to. 1. Don't use math, computer science, or programming language theory terminology without reason and explanation. +## Writing, Grammar, and Spelling -## Writing, Grammar, and Spelling - -Please don't worry about this too much, as a technical writer will review any new documentation or changes to catch these types of things. It's included here for reference, if interested. +Please don't worry about this too much, as a technical writer will review any new documentation or changes to catch these types of things. It's included here for reference, if interested. ### Tone & POV -We're aiming for a relatively casual tone in these tutorials and other documentation. This means that it should read like you're speaking directly to the reader rather than an academic tone. To this end, it is acceptable to use second person (you), sparingly. -It's also okay to use first person plural (we, us), sparingly, but don't use the first person singular (I, me), as there isn't an author byline for the reader to know who "I" is. Using "we" can be helpful to write active sentences (more below). +We're aiming for a relatively casual tone in these tutorials and other documentation. This means that it should read like you're speaking directly to the reader rather than an academic tone. To this end, it is acceptable to use second person (you), sparingly. +It's also okay to use first person plural (we, us), sparingly, but don't use the first person singular (I, me), as there isn't an author byline for the reader to know who "I" is. Using "we" can be helpful to write active sentences (more below). ### Active Voice & Unnecessary Words -Active sentences employ a clear subject that performs an action with a robust verb (e.g., Mary baked the cake.), as opposed to weak verbs such as *occur* and *happen.* Passive sentences typically incorporate '***to be'*** verbs (is, are, were, was, etc.), where the subject undergoes the action (e.g., he cake was baked by Mary). Although it's not possible to avoid all **to be** verbs, try to minimise them when possible. + +Active sentences employ a clear subject that performs an action with a robust verb (e.g., Mary baked the cake.), as opposed to weak verbs such as *occur* and *happen.* Passive sentences typically incorporate '***to be'*** verbs (is, are, were, was, etc.), where the subject undergoes the action (e.g., he cake was baked by Mary). Although it's not possible to avoid all **to be** verbs, try to minimise them when possible. The sentences below highlight issues and provide suggestions for improvement: @@ -84,37 +85,35 @@ The sentences below highlight issues and provide suggestions for improvement: It's best to eliminate unnecessary prepositional phrases, especially when using with the possessive. Avoid phrases like "the car of Susan." Instead, write "Susan's car." When prepositional phrases (e.g., those starting with by, for, in, of, on, etc.) are strung together, it makes for clumsy and awkward sentences. For example: "She went *on* a road trip *across* the mountains *to* take pictures." This sentence has three prepositional phrases back to back. You can improve it by removing at least one prepositional phrase, like this: "She took pictures on her roadtrip across the mountains." -Following these guidelines makes for more enjoyable reading experience. +Following these guidelines makes for more enjoyable reading experience. ### Spelling & Grammar - [Grammar Help at Grammarly](https://www.grammarly.com/blog/category/handbook/) - **Punctuation Preferences:** - - Oxford (serial) comma [We bought bread, milk, and peanut butter], so there is a final comma before the conjunction. - - Single space after a `.` period (full stop). - - Always use `'` for singular names/nouns ending in `s` and for plural nouns ending in `s` (e.g., Thomas’ and Companies’). Although the grammatically correct way to say and spell singular nouns ending in `s` is “Thomas’s”, it does look weird. It’s the consensus to treat every `s` as if it were a plural possessive, so instead write "Thomas'." Whenever possible, rephrase the sentence to avoid it completely. - - Place punctuation inside of quotation marks: OCaml is an "industrial-strength functional programming language with an emphasis on expressiveness and safety." (not "...safety".) - - Use **en dashes `–`** surrounded by spaces for 'asides' (as an alternative, you can use parentheses). Example: OCaml Multicore is – as my grandmother would say – an excellent upgrade. - - [Cambridge Dictionary: Punctuation](https://dictionary.cambridge.org/grammar/british-grammar/punctuation) - - [Differences in British & American](https://www.unr.edu/writing-speaking-center/student-resources/writing-speaking-resources/british-american-english), please use the British spelling. See below. - - [Another ^^](https://www.thepunctuationguide.com/british-versus-american-style.html) + - Oxford (serial) comma [We bought bread, milk, and peanut butter], so there is a final comma before the conjunction. + - Single space after a `.` period (full stop). + - Always use `'` for singular names/nouns ending in `s` and for plural nouns ending in `s` (e.g., Thomas’ and Companies’). Although the grammatically correct way to say and spell singular nouns ending in `s` is “Thomas’s”, it does look weird. It’s the consensus to treat every `s` as if it were a plural possessive, so instead write "Thomas'." Whenever possible, rephrase the sentence to avoid it completely. + - Place punctuation inside of quotation marks: OCaml is an "industrial-strength functional programming language with an emphasis on expressiveness and safety." (not "...safety".) + - Use **en dashes `–`** surrounded by spaces for 'asides' (as an alternative, you can use parentheses). Example: OCaml Multicore is – as my grandmother would say – an excellent upgrade. + - [Cambridge Dictionary: Punctuation](https://dictionary.cambridge.org/grammar/british-grammar/punctuation) + - [Differences in British & American](https://www.unr.edu/writing-speaking-center/student-resources/writing-speaking-resources/british-american-english), please use the British spelling. See below. + - [Another ^^](https://www.thepunctuationguide.com/british-versus-american-style.html) - **Spelling** - - [British spelling](http://www.tysto.com/uk-us-spelling-list.html) - - ise rather than -ize (organise vs organize) - - our, not or (flavour vs flavor) - - yse, not yze (analyse vs analyze) - - Double L : travelling vs traveling - - ae/oe vs e (manoeuvre vs maneuver) - - ence, not -ense (licence vs license) - - ogue, not og (catalogue vs catalog) - - learnt, not learned - - focussed / focusses (instead of the single s: focused / focuses) - - vs, not vs. as in American English. Same with Dr, Mr, Ms, Mrs instead of Dr., Mr., Ms., Mrs. - - Although programme is traditionally the UK spelling, **program** is more common. - -- **Capitalisation** - - Capitalise every word (except “little words” like of, and, or, etc.) in titles, aka “[Title Case](https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case).” Strangely, it is correct to capitalise “with” in a title. - - Use Title Case in headings / subheadings. Try to keep them under 7 words. - - Capitalise the first letter of bullet points, aka “[Sentence Case](https://apastyle.apa.org/style-grammar-guidelines/capitalization/sentence-case).” However, if it’s not a complete sentence in the bullet point, don’t use a period (full stop) unless it’s followed by other sentences. - + - [British spelling](http://www.tysto.com/uk-us-spelling-list.html) + - ise rather than -ize (organise vs organize) + - our, not or (flavour vs flavor) + - yse, not yze (analyse vs analyze) + - Double L : travelling vs traveling + - ae/oe vs e (manoeuvre vs maneuver) + - ence, not -ense (licence vs license) + - ogue, not og (catalogue vs catalog) + - learnt, not learned + - focussed / focusses (instead of the single s: focused / focuses) + - vs, not vs. as in American English. Same with Dr, Mr, Ms, Mrs instead of Dr., Mr., Ms., Mrs. + - Although programme is traditionally the UK spelling, **program** is more common. +- **Capitalisation** + - Capitalise every word (except “little words” like of, and, or, etc.) in titles, aka “[Title Case](https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case).” Strangely, it is correct to capitalise “with” in a title. + - Use Title Case in headings / subheadings. Try to keep them under 7 words. + - Capitalise the first letter of bullet points, aka “[Sentence Case](https://apastyle.apa.org/style-grammar-guidelines/capitalization/sentence-case).” However, if it’s not a complete sentence in the bullet point, don’t use a period (full stop) unless it’s followed by other sentences. diff --git a/Dockerfile b/Dockerfile index 2751f1f5bb..8698cc0c5e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -43,6 +43,7 @@ COPY --from=build /home/opam/_build/default/src/ocamlorg_web/bin/main.exe /bin/s COPY playground/asset playground/asset RUN git clone https://github.com/ocaml-web/html-compiler-manuals /manual +ADD data/v2 /v2 RUN git config --global --add safe.directory /var/opam-repository @@ -50,7 +51,8 @@ ENV DREAM_VERBOSITY=info \ OCAMLORG_HTTP_PORT=8080 \ OCAMLORG_MANUAL_PATH=/manual \ OCAMLORG_PKG_STATE_PATH=/var/package.state \ - OCAMLORG_REPO_PATH=/var/opam-repository/ + OCAMLORG_REPO_PATH=/var/opam-repository/ \ + OCAMLORG_V2_PATH=/v2 EXPOSE 8080 diff --git a/HACKING.md b/HACKING.md index e16c558d2d..a11941aa46 100644 --- a/HACKING.md +++ b/HACKING.md @@ -5,17 +5,18 @@ ### Setting Up the Project Before starting to hack, you need a properly configured development environment. Linux and macOS are supported and used daily by the core team. System dependencies include: -* Libev: http://software.schmorp.de/pkg/libev.html -* Oniguruma: https://github.com/kkos/oniguruma -* OpenSSL: https://www.openssl.org/ -* GNU Multiple Precision: https://gmplib.org/ -The project [`Dockerfile`](./Dockerfile) contains up-to-date system configuration instructions, as used to ship into production. It is written for the Alpine Linux distribution, but it is meant to be adapted to other environments such as Ubuntu, macOS+Homebrew, or others. The GitHub workflow file [`.github/workflows/ci.yml`](.github/workflows/ci.yml) also contains useful commands for Ubuntu and macOS. Since OCaml.org is mostly written in OCaml, a properly configured OCaml development environment is also required, but is not detailed here. Although Docker is used to ship, it is not a requirement to begin hacking. Currently, OCaml.org doesn't yet compile using OCaml 5; version 4.14 of the language is used. It is possible to run workflow files in `.github/workflows` using the [`nektos/act`](https://github.com/nektos/act) tool. For instance, the following command runs the CI checks through GitHub on each pull request (where `ghghgh` is replace by an _ad-hoc_ GitHub token, see: https://github.com/nektos/act#github_token) +* Libev: +* Oniguruma: +* OpenSSL: +* GNU Multiple Precision: + +The project [`Dockerfile`](./Dockerfile) contains up-to-date system configuration instructions, as used to ship into production. It is written for the Alpine Linux distribution, but it is meant to be adapted to other environments such as Ubuntu, macOS+Homebrew, or others. The GitHub workflow file [`.github/workflows/ci.yml`](.github/workflows/ci.yml) also contains useful commands for Ubuntu and macOS. Since OCaml.org is mostly written in OCaml, a properly configured OCaml development environment is also required, but is not detailed here. Although Docker is used to ship, it is not a requirement to begin hacking. Currently, OCaml.org doesn't yet compile using OCaml 5; version 4.14 of the language is used. It is possible to run workflow files in `.github/workflows` using the [`nektos/act`](https://github.com/nektos/act) tool. For instance, the following command runs the CI checks through GitHub on each pull request (where `ghghgh` is replace by an _ad-hoc_ GitHub token, see: ) + ``` act -s GITHUB_TOKEN=ghghgh .github/workflows/ci.yml -j build ``` - The Makefile contains many commands that can get you up and running. A typical workflow is to clone the repository after forking it. ``` @@ -59,12 +60,19 @@ This will restart the server on filesystem changes. ### Running Tests +#### Unit tests + You can run the unit test suite with: ```bash make test ``` +#### Load tests + +See the readme's for running load tests via [k6](./test/load-test/k6/README.md) +or [locust](./test/load-test/locust/README.md). + ### Building the Playground The OCaml Playground is compiled separately from the rest of the server. The generated assets can be found in @@ -84,13 +92,13 @@ After the dependencies have been installed, simply build the project to regenera make playground ``` -Once the compilation is complete and successuful, commit the newly-generated assets in OCaml.org's Git repo and merge the pull request. +Once the compilation is complete and successuful, commit the newly-generated assets in OCaml.org's Git repo and merge the pull request. ### Deploying Commits added on some branches are automatically deployed: -- `main` on -- `staging` on +* `main` on +* `staging` on The deployment pipeline is managed in , which listens to the `main` and `staging` branches and builds the site using the `Dockerfile` at the project's root. You can monitor the state of each deployment on [`deploy.ci.OCaml.org`](https://deploy.ci.OCaml.org/?repo=ocaml/OCaml.org). @@ -105,7 +113,7 @@ This will build the Docker image and run a Docker container with the port `8080` With the Docker container running, visit the site at . -The Docker images automatically build from the `live` and `staging` branches. They are then pushed to Docker Hub: https://hub.docker.com/r/ocurrent/v3.OCaml.org-server. +The Docker images automatically build from the `live` and `staging` branches. They are then pushed to Docker Hub: . ### Staging Pull Requests @@ -120,6 +128,7 @@ before they get merged. ### Managing Dependencies OCaml.org is using an opam switch that is local and bound to a pinned commit in `opam-repository`. This is intended to protect the build from upstream regressions. The opam repository is specified in three (3) places: + ``` Dockerfile Makefile @@ -129,6 +138,7 @@ Makefile When bringing up OCaml.org to a newer pin, the commit hash found it those files must be changed all at once. Once the opam repo pin is updated, the local switch must be updated using the following command: + ```sh opam repo set-url pin git+https://github.com/ocaml/opam-repository# ``` @@ -140,6 +150,10 @@ was upgraded in the process, the files `.ocamlformat` and `.github/workflows/ci.yml` must be modified with the currently installed version of OCamlFormat. +### Handling the Tailwind CSS + +The Tailwind CSS framework. The tailwind binary pulled from its GitHub [repo](https://github.com/tailwindlabs/tailwindcss). Download is performed by Dune during the build. When working on a local switch for hacking, you don't want `dune clean` to delete this binary. Just do `dune install tailwind` to have it installed in the local switch. + ## Repository Structure The following snippet describes the repository structure: diff --git a/README.md b/README.md index f4b4416672..9c06f1cb33 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Actions Status](https://github.com/ocaml/ocaml.org/workflows/CI/badge.svg)](https://github.com/ocaml/ocaml.org/actions) -This repository contains the sources of the OCaml website. It is served at https://ocaml.org/. +This repository contains the sources of the OCaml website. It is served at . ## Features @@ -62,6 +62,7 @@ Thank you to everyone who contributed to the development of this new version of In particular: For the groundwork on rethinking the sitemap, user flows, new content, design, and frontend, and package docs: + - Ashish Agarwal (Solvuu) - Kanishka Azimi (Solvuu) - Richard Davison (Solvuu) @@ -72,18 +73,22 @@ For the groundwork on rethinking the sitemap, user flows, new content, design, a - Anil Madhavapeddy (University of Cambridge) For the work on the package site infrastructure and UI: + - Jon Ludlam (OCaml Labs) - Jules Aguillon (Tarides) - Lucas Pluvinage (Tarides) For meticulously going through the website to find issues: + - Paul-Elliot Anglès d’Auriac (Tarides) For the work on the frontend designs and bringing them to life: + - Isabella Leandersson (OCaml Labs) - Asaad Mahmood (Tarides) For the work on the new content and reviewing the existing one: + - Christine Rose (Tarides) - Isabella Leandersson (OCaml Labs) diff --git a/asset/css/doc.css b/asset/css/doc.css index d46af508cd..b8892b8490 100644 --- a/asset/css/doc.css +++ b/asset/css/doc.css @@ -314,6 +314,15 @@ div.odoc .comment-delim { border-color: rgb(32, 68, 165); } +.navmap-tag.page-tag::after { + content: "P"; +} +.page-tag{ + color: rgb(32, 68, 165); + background-color: rgb(32, 68, 165); + border-color: rgb(32, 68, 165); +} + span.icon-expand > .navmap-tag, span.no-expand > .navmap-tag { color: white; @@ -344,10 +353,12 @@ span.arrow-expand.open { } span.sign-expand::before { - content: " \002B"; + content: "\002B"; display: flex; + justify-content: center; align-items: center; font-size: 1.25rem; + width: 1.25rem; margin-top: -0.25rem; } diff --git a/data/academic_institutions/Ashoka.md b/data/academic_institutions/Ashoka.md new file mode 100644 index 0000000000..af16274f65 --- /dev/null +++ b/data/academic_institutions/Ashoka.md @@ -0,0 +1,22 @@ +--- +name: Ashoka University +description: > + Ashoka University is a private, liberal arts and sciences university located in India. Known for its interdisciplinary approach and emphasis on critical thinking, the university offers a diverse range of undergraduate and graduate programs. +url: "https://www.ashoka.edu.in/" +logo: academic_institution/ashoka.png +continent: Asia +courses: + - name: Introduction to Computer Science + acronym: ICS + url: "https://aalok-thakkar.github.io/teaching/ics2025/ics2025.html" + year: 2025 + lecture_notes: true + exercises: true + enrollment: "150" + teacher: Aalok Thakkar, Debayan Gupta + description: | + This introductory course provides a foundational understanding of computational thinking as a problem-solving strategy, explores the core principles of computation, and introduces students to various subdisciplines within the field. Students will learn how to approach and solve problems both with and without code, with a strong emphasis on correctness, design, and style. The course is structured around two key computational models: the functional model, which views computation as the evaluation of mathematical functions, and the imperative model, which focuses on sequences of instructions that manipulate program state. By exploring these two perspectives, students will develop a deeper understanding of how different programming paradigms influence problem-solving and algorithm design. The course concludes with a series of lectures that offer disciplinary breadth through topics such as information theory, cryptography, compiler design, databases, numerical algorithms, quantitative modeling, and machine learning. +location: + lat: 28.99587 + long: 77.01165 +--- diff --git a/data/academic_institutions/bitspilani.md b/data/academic_institutions/bitspilani.md new file mode 100644 index 0000000000..b81603681a --- /dev/null +++ b/data/academic_institutions/bitspilani.md @@ -0,0 +1,19 @@ +--- +name: BITS Pilani (Pilani Campus) +description: > + BITS Pilani is a private science and engineering university in India. +url: "https://bits-pilani.ac.in/" +logo: academic_institution/bitspilani.png +continent: Asia +courses: + - name: Principles of Programming Languages + acronym: CS F301 + url: NA + year: 2024 + teacher: Dhruv Kumar + lecture_notes: false + video_recordings: false +location: + lat: 28.359481 + long: 75.588136 +--- diff --git a/data/books/learn-programming-with-ocaml.md b/data/books/learn-programming-with-ocaml.md new file mode 100644 index 0000000000..caa6993e58 --- /dev/null +++ b/data/books/learn-programming-with-ocaml.md @@ -0,0 +1,46 @@ +--- +title: "Learn Programming with OCaml" +slug: "learn-programming-with-ocaml" +description: > + This book is organised into three parts. The first one introduces + OCaml and targets beginners, whether they're programming beginners or + simply new to OCaml. Through small programs, the reader is introduced + to fundamental concepts of programming and of OCaml. The second and + third parts are dedicated to fundamental concepts of algorithmics and + should allow the reader to write programs in a structured and + efficient way. +authors: + - Jean-Christophe Filliâtre + - Sylvain Conchon +published: "2025" +cover: books/learn-programming-with-ocaml.jpg +language: + - english +links: + - description: PDF download + uri: https://usr.lmf.cnrs.fr/lpo/lpo.pdf +difficulty: beginner +pricing: free +--- + +Computer programming is hard to learn. Being a skillful programmer +requires imagination, anticipation, knowledge in algorithmics, the +mastery of a programming language, and above all, experience, as +difficulties are often hidden in details. This book synthesises our +experience as teachers and programmers. + +The programming style is essential. Given a programming language, the +same algorithm can be written in multiple ways, and some of them can +be both elegant and efficient. This is what the programmer must seek +at all costs and the reason why we choose a programming language for +this book rather than pseudo-code. Our choice is OCaml. + +This book is organised into three parts. The first one introduces +OCaml and targets beginners, whether they're programming beginners or +simply new to OCaml. Through small programs, the reader is introduced +to fundamental concepts of programming and of OCaml. The second and +third parts are dedicated to fundamental concepts of algorithmics and +should allow the reader to write programs in a structured and +efficient way. Algorithmic concepts are directly presented in the +syntax of OCaml and any code snippet from the book is available +online. diff --git a/data/changelog/merlin/2020-03-02-merlin-3.3.4~4.10preview1.md b/data/changelog/merlin/2020-03-02-merlin-3.3.4~4.10preview1.md deleted file mode 100644 index 470516f573..0000000000 --- a/data/changelog/merlin/2020-03-02-merlin-3.3.4~4.10preview1.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Merlin 3.3.4~4.10preview1 -tags: [merlin, platform] -changelog: | - Oops, we went looking but didn't find the changelog for this release 🙈 ---- - -This is a preview release that adds support for OCaml 4.10. -Short-path is disabled. Other versions of OCaml are not supported. diff --git a/data/changelog/ocaml-lsp/2022-07-28-ocaml-lsp-1.13.2~5.0preview.md b/data/changelog/ocaml-lsp/2022-07-28-ocaml-lsp-1.13.2~5.0preview.md deleted file mode 100644 index a5c6192261..0000000000 --- a/data/changelog/ocaml-lsp/2022-07-28-ocaml-lsp-1.13.2~5.0preview.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Ocaml-lsp 1.13.2~5.0preview -tags: [ocaml-lsp, platform] -changelog: | - Oops, we went looking but didn't find the changelog for this release 🙈 ---- diff --git a/data/changelog/ocaml-lsp/2022-12-16-ocaml-lsp-1.15.0~5.0preview1.md b/data/changelog/ocaml-lsp/2022-12-16-ocaml-lsp-1.15.0~5.0preview1.md deleted file mode 100644 index c7679035d2..0000000000 --- a/data/changelog/ocaml-lsp/2022-12-16-ocaml-lsp-1.15.0~5.0preview1.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Ocaml-lsp 1.15.0~5.0preview1 -tags: [ocaml-lsp, platform] -changelog: | - Oops, we went looking but didn't find the changelog for this release 🙈 ---- diff --git a/data/changelog/ocaml/2022-10-12-ocaml-5.0.beta1.md b/data/changelog/ocaml/2022-10-12-ocaml-5.0.beta1.md deleted file mode 100644 index fce229d48e..0000000000 --- a/data/changelog/ocaml/2022-10-12-ocaml-5.0.beta1.md +++ /dev/null @@ -1,185 +0,0 @@ ---- -title: OCaml 5.0.0 - First Beta -description: First beta release of OCaml 5.0.0 -tags: [ocaml] -changelog: | - ## Changes Since Last Alpha Release - - ### `Stdlib` Changes - - + [#11309](https://github.com/ocaml/ocaml/issues/11309), [#11424](https://github.com/ocaml/ocaml/issues/11424), [#11427](https://github.com/ocaml/ocaml/issues/11427), +[#11545](https://github.com/ocaml/ocaml/issues/11545): Add Domain.recommended_domain_count. - (Christiano Haesbaert, Konstantin Belousov, review by David Allsopp, - KC Sivaramakrishnan, Gabriel Scherer, Nicolas Ojeda Bar) - - - [#11423](https://github.com/ocaml/ocaml/issues/11423): Move the effect exceptions to the Effect module - (KC Sivaramakrishnan, Xavier Leroy, Florian Angeletti, review by - Florian Angeletti, Xavier Leroy, and KC Sivaramakrishnan) - - - [#11593](https://github.com/ocaml/ocaml/issues/11593): Remove Domain.at_each_spawn - (Florian Angeletti, review by Guillaume Munch-Maccagnoni - and KC Sivaramakrishnan) - - ### Bug Fixes - - - [#11303](https://github.com/ocaml/ocaml/issues/11303): Ensure that GC is not invoked from bounds check failures - (Stephen Dolan, review by Sadiq Jaffer and Xavier Leroy) - - - [#5299](https://github.com/ocaml/ocaml/issues/5299), [#4787](https://github.com/ocaml/ocaml/issues/4787), [#11138](https://github.com/ocaml/ocaml/issues/11138), [#11272](https://github.com/ocaml/ocaml/issues/11272), [#11506](https://github.com/ocaml/ocaml/issues/11506): To help debugging, `Caml_state` - now dynamically checks that the domain lock is held and fails - otherwise (with a fatal error at most entry points of the C API, or - systematically in debug mode). A new variable `Caml_state_opt` is - introduced and is `NULL` when the domain lock is not held. This - allows to test from C code if the current thread holds its domain lock. - (Guillaume Munch-Maccagnoni, review by Florian Angeletti, Damien - Doligez, Sadiq Jaffer, Xavier Leroy, and Gabriel Scherer) - - - [#11223](https://github.com/ocaml/ocaml/issues/11223): The serialisation format of custom blocks changed in 4.08, - but the deserialiser would still support the pre-4.08 format. OCaml - 5.x removed support for this old format and provided a clear error message - in this case. - (Hugo Heuzard, review by Gabriel Scherer) - - - [#11504](https://github.com/ocaml/ocaml/issues/11504), [#11522](https://github.com/ocaml/ocaml/issues/11522): Use static allocation for `caml_make_float_vect` in - no-flat-float-array mode, it's more efficient and avoids a race condition - (Xavier Leroy, report by Guillaume Munch-Maccagnoni, review by David Allsopp) - - - [#11461](https://github.com/ocaml/ocaml/issues/11461), [#11466](https://github.com/ocaml/ocaml/issues/11466): Fix `gethostbyaddr` for IPv6 arguments and make it domain-safe - (Olivier Nicole, Nicolás Ojeda Bär, David Allsopp and Xavier Leroy, - review by the same) - - - [#11479](https://github.com/ocaml/ocaml/issues/11479): Make Unix.symlink domain-safe on Windows - (Olivier Nicole, review by Xavier Leroy and David Allsopp) - - - [#11294](https://github.com/ocaml/ocaml/issues/11294): Switch minimum required autoconf to 2.71. - (David Allsopp, review by Xavier Leroy) - - - [#11370](https://github.com/ocaml/ocaml/issues/11370), [#11373](https://github.com/ocaml/ocaml/issues/11373): Don't pass CFLAGS to flexlink during configure. - (David Allsopp, report by William Hu, review by Xavier Leroy and - Sébastien Hinderer) - - - [#11487](https://github.com/ocaml/ocaml/issues/11487): Thwart FMA test optimization during configure - (William Hu, review by David Allsopp and Sébastien Hinderer) - - - [#11468](https://github.com/ocaml/ocaml/issues/11468): Fix regression from [#10186](https://github.com/ocaml/ocaml/issues/10186) (OCaml 4.13) detecting IPv6 on Windows for - mingw-w64 i686 port. - (David Allsopp, review by Xavier Leroy and Sébastien Hinderer) - - - [#11482](https://github.com/ocaml/ocaml/issues/11482), [#11542](https://github.com/ocaml/ocaml/issues/11542): Fix random crash in large closure allocation - (Damien Doligez, report by Thierry Martinez and Vincent Laviron, review by - Xavier Leroy) - - - [#11508](https://github.com/ocaml/ocaml/issues/11508), [#11509](https://github.com/ocaml/ocaml/issues/11509): make Bytes.escaped domain-safe - (Christiano Haesbaert and Gabriel Scherer, - review by Xavier Leroy, - report by Jan Midtgaard and Tom Kelly) - - - [#11516](https://github.com/ocaml/ocaml/issues/11516), [#11524](https://github.com/ocaml/ocaml/issues/11524): Fix the `deprecated_mutable` attribute. - (Chris Casinghino, review by Nicolás Ojeda Bär and Florian Angeletti) - - - [#11576](https://github.com/ocaml/ocaml/issues/11576): Fix bug in Bigarray.Genarray.init in the the case of zero-dimensional - arrays. - (Nicolás Ojeda Bär, Jeremy Yallop, report by Masayuki Takeda, review by Jeremy - Yallop and Florian Angeletti) - - - [#11587](https://github.com/ocaml/ocaml/issues/11587): Prevent integer comparison from being used on pointers - (Vincent Laviron, review by Gabriel Scherer) - - ### Documentation Changes - - - [#11093](https://github.com/ocaml/ocaml/issues/11093): Add tutorials on parallelism features and the relaxed memory model - (KC Sivaramakrishnan, review by Damien Doligez, Anil Madhavapeddy, Gabriel - Scherer, Thomas Leonard, Tom Ridge, Xavier Leroy, Luc Maranget, Fabrice - Buoro, Olivier Nicole, Guillaume Munch-Maccagnoni, Jacques-Henri Jourdan) ---- - -The release of OCaml 5.0.0 is drawing near. -The standard library has been stabilized and many opam packages already -work with this release. -After two alpha releases, we have released the first beta version to help you update your software and libraries ahead of the release (see below for the installation instructions). - -If you find any bugs, please report them [on GitHub issues](https://github.com/ocaml/ocaml/issues). - -Compared to the last alpha release, this beta contains many small, internal -runtime fixes (in particular in the `systhreads` library). - -At the user level, the interface of the Domain and Effect module has been tweaked to be (hopefully) more forward-compatible: - -- Exceptions related to effects are now defined in the Effecŧ module. -- The value `Domain.recommended_domain_count` is no longer a constant and the function `Domain.at_each_spawn` has been removed. - -With those changes, the standard library should be stable now. - -If you are interested in the ongoing list of bug fixes, the -updated change log for OCaml 5.0.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.0/Changes). - -You can also follow the state of the opam ecosystem on [this `opam-repository` issues](https://github.com/ocaml/opam-repository/issues/21526), and at [check.ocamllabs.io](http://check.ocamllabs.io/) - -A short summary of the changes since the last alpha release is also available -below. - - -Installation Instructions -------------------------- - -The base compiler can be installed as an opam switch with the following commands -on opam 2.1: -```bash -opam update -opam switch create 5.0.0~beta1 -``` - -For previous versions of opam, the switch creation command line is slightly more verbose: -```bash -opam update -opam switch create 5.0.0~beta1 --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` - -It might also be interesting to check the new support for parallelism by installing -the `domainslib` library with - -```bash -opam install domainslib -``` - -The source code for the beta release is also available at these addresses: - -* [https://github.com/ocaml/ocaml/archive/5.0.0-beta1.tar.gz](https://github.com/ocaml/ocaml/archive/5.0.0-beta1.tar.gz) -* [https://caml.inria.fr/pub/distrib/ocaml-5.0/ocaml-5.0.0~beta1.tar.gz](https://caml.inria.fr/pub/distrib/ocaml-5.0/ocaml-5.0.0~beta1.tar.gz) - -## Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: -```bash -opam update -opam switch create ocaml-variants.5.0.0~beta1+options -``` -where `option_list` is a comma-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: -```bash -opam switch create 5.0.0~beta1+flambda+nffa ocaml-variants.5.0.0~beta1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` -The command line above is slightly more complicated for opam versions before 2.1: -```bash -opam update -opam switch create --packages=ocaml-variants.5.0.0~beta1+options, --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` - -In both cases, all available options can be listed with `opam search ocaml-option`. - -## Optional opam Alpha Repository - -During the beta release, if your dependencies are not yet compatible with OCaml 5.0.0, -you might want to check the alpha opam repository: [https://github.com/kit-ty-kate/opam-alpha-repository](https://github.com/kit-ty-kate/opam-alpha-repository). - -Which can be installed with -```bash -opam repo add alpha git+https://github.com/kit-ty-kate/opam-alpha-repository.git -``` -You can check that the alpha repository has been correctly installed with -```bash -$ opam repo -<><> Repository configuration for switch 5.0.0~beta1 <><><><><><><><><><><><><> - 1 alpha git+https://github.com/kit-ty-kate/opam-alpha-repository.git - 2 default https://opam.ocaml.org -``` -This alpha repository contains various fixes that are in the process of being upstreamed, -but it should be less and less required with the progress of the beta release. diff --git a/data/changelog/ocaml/2022-11-28-ocaml-5.0.beta2.md b/data/changelog/ocaml/2022-11-28-ocaml-5.0.beta2.md deleted file mode 100644 index 2cb6589c40..0000000000 --- a/data/changelog/ocaml/2022-11-28-ocaml-5.0.beta2.md +++ /dev/null @@ -1,136 +0,0 @@ ---- -title: OCaml 5.0.0 - Second Beta -description: Second beta release of OCaml 5.0.0 -tags: [ocaml] -changelog: | - ## Changes since the first beta - - ### Configuration changes - - - [#11097](https://github.com/ocaml/ocaml/issues/11097): Build native-code - compilers on NetBSD/aarch64 (Kate Deplaix, review by Anil Madhavapeddy) - - ### Bug fixes - - - [#10875](https://github.com/ocaml/ocaml/issues/10875), - +[#11731](https://github.com/ocaml/ocaml/issues/11731): Add option to allocate - fiber stacks and sigaltstacks with mmap(MAP_STACK) instead of malloc. This is - exposed via a configure –enable-mmap-map-stack option, and is enabled by default - on OpenBSD where it is mandatory. (Anil Madhavapeddy, review by Gabriel Scherer, - Tom Kelly, Michael Hendricks and KC Sivaramakrishnan). - - [#11652](https://github.com/ocaml/ocaml/issues/11652): Fix benign off-by-one - error in Windows implementation of caml_mem_map. (David Allsopp, review by - Gabriel Scherer) - - [#11669](https://github.com/ocaml/ocaml/issues/11669), - [#11704](https://github.com/ocaml/ocaml/issues/11704): Fix construction of - Effect.Unhandled exceptions in the bytecode interpreter. (David Allsopp and - Xavier Leroy, report by Samuel Hym, review by Xavier Leroy and Gabriel Scherer) - - [#11184](https://github.com/ocaml/ocaml/issues/11184), - +[#11670](https://github.com/ocaml/ocaml/issues/11670): Stop calling ranlib on - created / installed libraries (Sébastien Hinderer and Xavier Leroy, review by - the same) - - [#11194](https://github.com/ocaml/ocaml/issues/11194), - [#11609](https://github.com/ocaml/ocaml/issues/11609): Fix inconsistent type - variable names in “unbound type var” messages (Ulysse Gérard and Florian - Angeletti, review Florian Angeletti and Gabriel Scherer) - - [#11622](https://github.com/ocaml/ocaml/issues/11622): Prevent stack overflow - when printing a constructor or record mismatch error involving recursive types. - (Florian Angeletti, review by Gabriel Scherer) - - [#11662](https://github.com/ocaml/ocaml/issues/11662), - [#11673](https://github.com/ocaml/ocaml/issues/11673): fix a memory leak when - using Dynlink, the bug was only present in development version of OCaml 5. - (Stephen Dolan, report by Andre Maroneze, review by Gabriel Scherer) - - [#11732](https://github.com/ocaml/ocaml/issues/11732): Ensure that types from - packed modules are always generalised (Stephen Dolan and Leo White, review by - Jacques Garrigue) - - [#11737](https://github.com/ocaml/ocaml/issues/11737): Fix segfault condition - in Unix.stat under Windows in the presence of multiple threads. (Marc Lasson, - Nicolás Ojeda Bär, review by Gabriel Scherer and David Allsopp) - - ### Documentation - - - [#11193](https://github.com/ocaml/ocaml/issues/11193), - [#11227](https://github.com/ocaml/ocaml/issues/11227): documentation on - concurrency safety for mutable data types and states in the standard library. A - unsynchronized_access alert have been added for functions that require user - synchronizations on concurrent access. The new alert is diabled by default. - (Florian Angeletti, review by François Pottier and KC Sivaramakrishnan ) - - [#11526](https://github.com/ocaml/ocaml/issues/11526), add a unstable alert to - the Domain and Effect modules. The new alert is disabled by default. (Florian - Angeletti, review by Nicolás Ojeda Bär, Daniel Bünzli, and Kate Deplaix) - - [#11640](https://github.com/ocaml/ocaml/issues/11640): Add Flambda - commonly-used options to the ocamlopt manpage (Amandine Nangah, review by David - Allsopp, Florian Angeletti, Sébastien Hinderer, and Vincent Laviron) ---- - -The release of OCaml 5.0.0 is drawing close. - -In order to test the most recent bug fixes and to help you update your software -and libraries ahead of the release, we have released a second beta version of -OCaml 5.0.0, (see below for the installation instructions). - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -Compared to the first beta release, this second beta contains many small -internal standard library fixes, one configuration fix and many small bug fixes. - -We also have few updates of the documentation, which introduce two new alerts: -one for the unstable modules Domain and Effect, and another for functions doing -unsynchronized_access to mutable state in the standard library. Those two alerts -are disabled by default, but are available for interested users. - -The first release candidate for OCaml 5.0.0 is expected to follow closely this -second beta release. - -If you are interested in the ongoing list of bug fixes, the updated change log -for OCaml 5.0.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.0/Changes). - -You can also follow the state of the opam ecosystem on [http://check.ocamllabs.io/](http://check.ocamllabs.io/). - -A short summary of the changes since the first beta release is also available below. - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands -on opam 2.1: -```bash -opam update -opam switch create 5.0.0~beta2 -``` - -For previous versions of opam, the switch creation command line is slightly more verbose: -```bash -opam update -opam switch create 5.0.0~beta2 --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` - -It might also be interesting to check the new support for parallelism by installing -the `domainslib` library with -```bash -opam install domainslib -``` - -The source code for the beta release is also available at these addresses: - -* [https://github.com/ocaml/ocaml/archive/5.0.0-beta2.tar.gz](https://github.com/ocaml/ocaml/archive/5.0.0-beta2.tar.gz) -* [https://caml.inria.fr/pub/distrib/ocaml-5.0/ocaml-5.0.0~beta2.tar.gz](https://caml.inria.fr/pub/distrib/ocaml-5.0/ocaml-5.0.0~beta2.tar.gz) - -## Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: -```bash -opam update -opam switch create ocaml-variants.5.0.0~beta2+options -``` -where `option_list` is a comma-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: -```bash -opam switch create 5.0.0~beta2+flambda+nffa ocaml-variants.5.0.0~beta2+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` -The command line above is slightly more complicated for opam versions before 2.1: -```bash -opam update -opam switch create --packages=ocaml-variants.5.0.0~beta2+options, --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` - -In both cases, all available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2022-12-06-ocaml-5.0.rc1.md b/data/changelog/ocaml/2022-12-06-ocaml-5.0.rc1.md deleted file mode 100644 index b2751c4371..0000000000 --- a/data/changelog/ocaml/2022-12-06-ocaml-5.0.rc1.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: OCaml 5.0.0 - First release candidate -description: First Release Candidate of OCaml 5.0.0 -tags: [ocaml] -changelog: | - ## Changes Since the Second Beta Release - - ### Bug Fixes - - - [#11776](https://github.com/ocaml/ocaml/issues/11776): Extend environment with functor parameters in `strengthen_lazy`. - (Chris Casinghino and Luke Maurer, review by Gabriel Scherer) - - - [#11533](https://github.com/ocaml/ocaml/issues/11533), [#11534](https://github.com/ocaml/ocaml/issues/11534): follow synonyms again in #show_module_type - (this had stopped working in 4.14.0) - (Gabriel Scherer, review by Jacques Garrigue, report by Yaron Minsky) ---- - - -The release of OCaml version 5.0.0 is imminent. As a final step before the -release, we are publishing a release candidate that you can test while waiting -for the release in the upcoming weeks. - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -Compared to the second beta release, this release contains one toplevel bug fix -and a minor type system fix. - -If you are interested by the bug fixes beyond the new Multicore runtime, the -full change log for OCaml 5.0.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.0/Changes) - -A short summary of the changes since the second beta release is also available below. - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands on opam 2.1: -```bash -opam update -opam switch create 5.0.0~rc1 -``` -For previous version of opam, the switch creation command line is slightly more verbose: -```bash -opam update -opam switch create 5.0.0~rc1 --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` -It might be also interesting to check the new support for parallelism by installing the `domainslib` library with -```bash -opam install domainslib -``` -The source code for the release candidate is also directly available on: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.0.0-rc1.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.0/ocaml-5.0.0~rc1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: -```bash -opam update -opam switch create ocaml-variants.5.0.0~rc1+options -``` -where `` is a comma-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: -```bash -opam switch create 5.0.0~rc1+flambda+nffa ocaml-variants.5.0.0~rc1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -The command line above is slightly more complicated for opam versions before 2.1: - -```bash -opam update -opam switch create --packages=ocaml-variants.5.0.0~rc1+options, --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` -In both cases, all available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2022-12-08-ocaml-4.14.1.rc1.md b/data/changelog/ocaml/2022-12-08-ocaml-4.14.1.rc1.md deleted file mode 100644 index 83a85be303..0000000000 --- a/data/changelog/ocaml/2022-12-08-ocaml-4.14.1.rc1.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: OCaml 4.14.1 - Release candidate -description: Release Candidate of OCaml 4.14.1 -tags: [ocaml] -changelog: | - ## Changes Since OCaml 4.14.0 - - - ### Compiler User-Interface and Warnings: - - - [#11184](https://github.com/ocaml/ocaml/issues/11184), [#11670](https://github.com/ocaml/ocaml/issues/11670): Stop calling `ranlib` on created / installed libraries - (Sébastien Hinderer and Xavier Leroy, review by the same) - - ### Build System: - - - [#11370](https://github.com/ocaml/ocaml/issues/11370), [#11373](https://github.com/ocaml/ocaml/issues/11373): Don't pass CFLAGS to flexlink during configure. - (David Allsopp, report by William Hu, review by Xavier Leroy and - Sébastien Hinderer) - - - [#11487](https://github.com/ocaml/ocaml/issues/11487): Thwart FMA test optimisation during configure - (William Hu, review by David Allsopp and Sébastien Hinderer) - - ### Bug Fixes: - - - [#10768](https://github.com/ocaml/ocaml/issues/10768), [#11340](https://github.com/ocaml/ocaml/issues/11340): Fix typechecking regression when combining first class - modules and GADTs. - (Jacques Garrigue, report by François Thiré, review by Matthew Ryan) - - - [#11204](https://github.com/ocaml/ocaml/issues/11204): Fix regression introduced in 4.14.0 that would trigger Warning 17 when - calling virtual methods introduced by constraining the self type from within - the class definition. - (Nicolás Ojeda Bär, review by Leo White) - - - [#11263](https://github.com/ocaml/ocaml/issues/11263), [#11267](https://github.com/ocaml/ocaml/issues/11267): caml/{memory,misc}.h: check whether `_MSC_VER` is defined - before using it to ensure that the headers can always be used in code which - turns on `-Wundef` (or equivalent). - (David Allsopp and Nicolás Ojeda Bär, review by Nicolás Ojeda Bär and - Sébastien Hinderer) - - - [#11314](https://github.com/ocaml/ocaml/issues/11314), [#11416](https://github.com/ocaml/ocaml/issues/11416): fix non-informative error message for module inclusion - (Florian Angeletti, report by Thierry Martinez, review by Gabriel Scherer) - - - [#11358](https://github.com/ocaml/ocaml/issues/11358), [#11379](https://github.com/ocaml/ocaml/issues/11379): Refactor the initialisation of bytecode threading, - This avoids a "dangling pointer" warning of GCC 12.1. - (Xavier Leroy, report by Armaël Guéneau, review by Gabriel Scherer) - - - [#11387](https://github.com/ocaml/ocaml/issues/11387), module type with constraints no longer crash the compiler in presence - of both shadowing warnings and the `-bin-annot` compiler flag. - (Florian Angeletti, report by Christophe Raffalli, review by Gabriel Scherer) - - - [#11392](https://github.com/ocaml/ocaml/issues/11392), [#11392](https://github.com/ocaml/ocaml/issues/11392): assertion failure with -rectypes and external definitions - (Gabriel Scherer, review by Florian Angeletti, report by Dmitrii Kosarev) - - - [#11417](https://github.com/ocaml/ocaml/issues/11417): Fix regression allowing virtual methods in non-virtual classes. - (Leo White, review by Florian Angeletti) - - - [#11468](https://github.com/ocaml/ocaml/issues/11468): Fix regression from [#10186](https://github.com/ocaml/ocaml/issues/10186) (OCaml 4.13) detecting IPv6 on Windows for - mingw-w64 i686 port. - (David Allsopp, review by Xavier Leroy and Sébastien Hinderer) - - - [#11489](https://github.com/ocaml/ocaml/issues/11489), [#11496](https://github.com/ocaml/ocaml/issues/11496): More prudent deallocation of alternate signal stack - (Xavier Leroy, report by @rajdakin, review by Florian Angeletti) - - - [#11516](https://github.com/ocaml/ocaml/issues/11516), [#11524](https://github.com/ocaml/ocaml/issues/11524): Fix the `deprecated_mutable` attribute. - (Chris Casinghino, review by Nicolás Ojeda Bär and Florian Angeletti) - - - [#11194](https://github.com/ocaml/ocaml/issues/11194), [#11609](https://github.com/ocaml/ocaml/issues/11609): Fix inconsistent type variable names in "unbound type var" - messages - (Ulysse Gérard and Florian Angeletti, review Florian Angeletti and - Gabriel Scherer) - - - [#11622](https://github.com/ocaml/ocaml/issues/11622): Prevent stack overflow when printing a constructor or record - mismatch error involving recursive types. - (Florian Angeletti, review by Gabriel Scherer) - - - [#11732](https://github.com/ocaml/ocaml/issues/11732): Ensure that types from packed modules are always generalised - (Stephen Dolan and Leo White, review by Jacques Garrigue) - - - [#11737](https://github.com/ocaml/ocaml/issues/11737): Fix segfault condition in `Unix.stat` under Windows in the presence of - multiple threads. - (Marc Lasson, Nicolás Ojeda Bär, review by Gabriel Scherer and David Allsopp) - - - [#11776](https://github.com/ocaml/ocaml/issues/11776): Extend environment with functor parameters in `strengthen_lazy`. - (Chris Casinghino and Luke Maurer, review by Gabriel Scherer) - - - [#11533](https://github.com/ocaml/ocaml/issues/11533), [#11534](https://github.com/ocaml/ocaml/issues/11534): follow synonyms again in `#show_module_type` - (this had stopped working in 4.14.0) - (Gabriel Scherer, review by Jacques Garrigue, report by Yaron Minsky) - - - [#11768](https://github.com/ocaml/ocaml/issues/11768), [#11788](https://github.com/ocaml/ocaml/issues/11788): Fix crash at start-up of bytecode programs in - no-naked-pointers mode caused by wrong initialisation of `caml_global_data` - (Xavier Leroy, report by Etienne Millon, review by Gabriel Scherer) ---- - -The release of OCaml version 4.14.1 is imminent. - -This companion release to the OCaml 5.0.0 release will backport many safe bug -fixes from the currently experimental 5.0 branch to the stable 4.14 branch. -A full list of bug fixes is available below. - -In order to ensure that the future release works as expected, we are testing -a release candidate during the upcoming weeks. - -If you find any bugs, please report them here on [GitHub](https://github.com/ocaml/ocaml/issues). - ----- - - -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands on opam 2.1: -``` -opam update -opam switch create 4.14.1~rc1 -``` -For previous version of opam, the switch creation command line is slightly more verbose: -``` -opam update -opam switch create 4.14.1~rc1 --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` -It might be also interesting to check the new support for parallelism by installing the `domainslib` library with -``` -opam install domainslib -``` -The source code for the release candidate is available on - -- [GitHub](https://github.com/ocaml/ocaml/archive/4.14.1-rc1.tar.gz) -- [Inria archives](https://caml.inria.fr/pub/distrib/ocaml-4.14/) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: -```bash -opam update -opam switch create ocaml-variants.4.14.1~rc1+options -``` -where `` is a comma-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: -```bash -opam switch create 4.14.1~rc1+flambda+nffa ocaml-variants.4.14.1~rc1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` -The command line above is slightly more complicated for opam versions before 2.1: -```bash -opam update -opam switch create --packages=ocaml-variants.4.14.1~rc1+options, --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` -In both cases, all available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2023-04-14-ocaml-5.1.alpha1.md b/data/changelog/ocaml/2023-04-14-ocaml-5.1.alpha1.md deleted file mode 100644 index a86bea8f7c..0000000000 --- a/data/changelog/ocaml/2023-04-14-ocaml-5.1.alpha1.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: OCaml 5.1.0 - First Alpha -description: First Alpha Release of OCaml 5.1.0 -tags: [ocaml] ---- - -Four months after the release of OCaml 5.0.0, the set of new features for the -future version 5.1.0 of OCaml has been frozen. We are thus happy to announce the -first alpha release for OCaml 5.1.0. - -This alpha version is here to help fellow hackers join us early in our bug -hunting and opam ecosystem fixing fun (see below for the installation instructions). -The progresses on stabilising the ecosystem are tracked on the [opam readiness for 5.1.0 meta-issue](https://github.com/ocaml/opam-repository/issues/23669). - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -Note that this early alpha version is missing two important fixes for the garbage -collector and Windows support. Those fixes will be available before the beta. -The full release is expected in July. - -If you are interested in the ongoing list of new features and bug fixes, the -updated change log for OCaml 5.1.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.1/Changes). - - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands -on opam 2.1: - -```bash -opam update -opam switch create 5.1.0~alpha1 -``` - -For previous version of opam, the switch creation command line is slightly more verbose: - -```bash -opam update -opam switch create 5.1.0~alpha1 --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` - -The source code for the alpha is also available at these addresses: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.1.0-alpha1.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.1/ocaml-5.1.0~alpha1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: - -```bash -opam update -opam switch create ocaml-variants.5.1.0~alpha1+options -``` - -where `option_list` is a space separated list of `ocaml-option-*` packages. For instance, for a flambda and no-flat-float-array switch: - -```bash -opam switch create 5.1.0~alpha1+flambda+nffa ocaml-variants.5.1.0~alpha1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -The command line above is slightly more complicated for opam version anterior to 2.1: - - -```bash -opam update -opam switch create --packages=ocaml-variants.5.1.0~alpha1+options, --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` -In both cases, all available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2023-06-01-ocaml-5.1.alpha2.md b/data/changelog/ocaml/2023-06-01-ocaml-5.1.alpha2.md deleted file mode 100644 index 5228d027ea..0000000000 --- a/data/changelog/ocaml/2023-06-01-ocaml-5.1.alpha2.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: OCaml 5.1.0 - Second Alpha -description: Second Alpha Release of OCaml 5.1.0 -tags: [ocaml] -changelog: | - ### Runtime System - - - [#11589](https://github.com/ocaml/ocaml/issues/11589), [#11903](https://github.com/ocaml/ocaml/issues/11903): Modify the GC pacing code to make sure the GC keeps - up with allocations in the presence of idle domains. - (Damien Doligez and Stephen Dolan, report by Florian Angeletti, - review by KC Sivaramakrishnan and Sadiq Jaffer) - - * (*breaking change*) [#11865](https://github.com/ocaml/ocaml/issues/11865), [#11868](https://github.com/ocaml/ocaml/issues/11868), [#11876](https://github.com/ocaml/ocaml/issues/11876): Clarify that the operations of a custom - block must never access the OCaml runtime. The previous - documentation only mentioned the main illicit usages. In particular, - since OCaml 5.0, it is no longer safe to call - `caml_remove_global_root` or `caml_remove_generational_global_root` - from within the C finalizer of a custom block, or within the - finalization function passed to `caml_alloc_final`. As a workaround, - such a finalization operation can be registered with `Gc.finalize` - instead, which guarantees to run the finalizer at a safe point. - (Report by Timothy Bourke, discussion by Yotam Barnoy, Timothy - Bourke, Sadiq Jaffer, Xavier Leroy, Guillaume Munch-Maccagnoni, and - Gabriel Scherer) - - + [#11827](https://github.com/ocaml/ocaml/issues/11827), +[#12249](https://github.com/ocaml/ocaml/issues/12249): Restore prefetching for GC marking - (Fabrice Buoro and Stephen Dolan, review by Gabriel Scherer and Sadiq Jaffer) - - - [#12131](https://github.com/ocaml/ocaml/issues/12131): Simplify implementation of weak hash sets, fixing a - performance regression. (Nick Barnes, review by François Bobot, - Alain Frisch and Damien Doligez). - - - [#12231](https://github.com/ocaml/ocaml/issues/12231): Support MinGW-w64 11.0 winpthreads library, where the macro - to set up to get flexdll working changed - (David Allsopp and Samuel Hym, light review by Xavier Leroy) - - ### Type System - - * (*breaking change*) [#12189](https://github.com/ocaml/ocaml/issues/12189), [#12211](https://github.com/ocaml/ocaml/issues/12211): anonymous row variables in explicitly polymorphic type - annotation, e.g. `'a. [< X of 'a ] -> 'a`, are now implicitly - universally quantified (in other words, the example above is now read - as `'a 'r. ([< X of 'a ] as 'r) -> 'a`). - (Florian Angeletti and Gabriel Scherer, review by Jacques Garrigue) - - ### Code Generation And Optimizations - - - [#11712](https://github.com/ocaml/ocaml/issues/11712), [#12258](https://github.com/ocaml/ocaml/issues/12258), [#12261](https://github.com/ocaml/ocaml/issues/12261): s390x / IBM Z multicore support: - OCaml & C stack separation; dynamic stack size checks; fiber and - effects support. - (Aleksei Nikiforov, with help from Vincent Laviron and Xavier Leroy, - additional suggestions by Luc Maranget, - review by the same and KC Sivaramakrishnan) - - ### Internal/compiler-libs Changes - - + [#12119](https://github.com/ocaml/ocaml/issues/12119), +[#12188](https://github.com/ocaml/ocaml/issues/12188), +[#12191](https://github.com/ocaml/ocaml/issues/12191): mirror type constraints on value binding in the - parsetree: - the constraint `typ` in `let pat : typ = exp` is now directly stored - in the value binding node in the parsetree. - (Florian Angeletti, review by Richard Eisenberg) - - ### Bug Fixes - - - [#11846](https://github.com/ocaml/ocaml/issues/11846): Mark rbx as destroyed at C call for Win64 (mingw-w64 and Cygwin64). - Reserve the shadow store for the ABI in the c_stack_link struct instead of - explictly when calling C functions. This simultaneously reduces the number of - stack pointer manipulations and also fixes a bug when calling noalloc - functions where the shadow store was not being reserved. - (David Allsopp, report by Vesa Karvonen, review by Xavier Leroy and - KC Sivaramakrishnan) - - - [#12170](https://github.com/ocaml/ocaml/issues/12170): fix pthread_geaffinity_np configure check for android - (David Allsopp, review by Sébastien Hinderer) - - - [#12252](https://github.com/ocaml/ocaml/issues/12252): Fix shared library build error on RISC-V. - (Edwin Török, review by Nicolás Ojeda Bär and Xavier Leroy) - - - [#12255](https://github.com/ocaml/ocaml/issues/12255), [#12256](https://github.com/ocaml/ocaml/issues/12256): Handle large signal numbers correctly (Nick Barnes, - review by David Allsopp). - - - [#12277](https://github.com/ocaml/ocaml/issues/12277): ARM64, fix a potential assembler error for very large functions by - emitting stack reallocation code before the body of the function. - (Xavier Leroy, review by KC Sivaramakrishnan) ---- - -With the progress of the ongoing stabilisation effort for OCaml 5.1.0, -I am happy to announce a second alpha release for OCaml 5.1.0. - -This second alpha release contains many noteworthy fixes: - -- a long-awaited GC fix -- a Windows ABI fix - -as announced in the first alpha but also - -- a compiler-libs (parsetree) fix -- a type system compatibility enhancement change -- a restored backed for s390x/IBM Z - -The full list of changes since the first alpha is available below. - -Once most major OCaml tools are updated to the last compiler-libs changes, -we will switch to beta releases. Hopefully, this will happen in the upcoming -weeks. The progress on stabilising the ecosystem is tracked on the -[opam readiness for 5.1.0 meta-issue](https://github.com/ocaml/opam-repository/issues/23669). - -Currently, the release is still planned for around July. - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -If you are interested in the ongoing list of new features and bug fixes, the -updated change log for OCaml 5.1.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.1/Changes). - - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands -on opam 2.1: - -```bash -opam update -opam switch create 5.1.0~alpha2 -``` - -The source code for the alpha is also available at these addresses: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.1.0-alpha2.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.1/ocaml-5.1.0~alpha2.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: - -```bash -opam update -opam switch create ocaml-variants.5.1.0~alpha2+options -``` - -where `option_list` is a space-separated list of `ocaml-option-*` packages. For instance, for a flambda and no-flat-float-array switch: - -```bash -opam switch create 5.1.0~alpha2+flambda+nffa ocaml-variants.5.1.0~alpha2+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2023-07-04-ocaml-5.1.beta1.md b/data/changelog/ocaml/2023-07-04-ocaml-5.1.beta1.md deleted file mode 100644 index b953988b07..0000000000 --- a/data/changelog/ocaml/2023-07-04-ocaml-5.1.beta1.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: OCaml 5.1.0 - First Beta -description: First Beta Release of OCaml 5.1.0 -tags: [ocaml] -changelog: | - ### Runtime System Bugfix - - - [#12037](https://github.com/ocaml/ocaml/issues/12037): Fix some data races by using volatile when necessary - (Fabrice Buoro and Olivier Nicole, review by Guillaume Munch-Maccagnoni, - Gabriel Scherer and Luc Maranget) - - - [#12253](https://github.com/ocaml/ocaml/issues/12253), [#12342](https://github.com/ocaml/ocaml/issues/12342): Fix infinite loop in signal handling. - (Guillaume Munch-Maccagnoni, report by Thomas Leonard, review by - KC Sivaramakrishnan and Sadiq Jaffer) - - ### Windows Bugfix - - - [#12184](https://github.com/ocaml/ocaml/issues/12184), [#12320](https://github.com/ocaml/ocaml/issues/12320): Sys.rename Windows fixes on directory corner cases. - (Jan Midtgaard, review by Anil Madhavapeddy) - ---- - -After two alpha releases, the release of OCaml 5.1.0 is drawing near. -We have thus released a first beta version of OCaml 5.1.0 to help you update your softwares and libraries ahead of the release (see below for the installation instructions). -Compared to the last alpha release, this beta contains two subtle internal runtime fixes and one Windows fix. -Overall, the opam ecosystem looks in a good shape for the first beta release. - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -Nearly all core development tools support OCaml 5.1.0, and you can follow the last remaining wrinkles on the -[opam readiness for 5.1.0 meta-issue](https://github.com/ocaml/opam-repository/issues/23669). - -Currently, the release is planned for the end of July or the beginning of August. - -If you are interested in full list of features and bug fixes of the new OCaml version, the -updated change log for OCaml 5.1.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.1/Changes). - - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands -on opam 2.1: - -```bash -opam update -opam switch create 5.1.0~beta1 -``` - -The source code for the alpha is also available at these addresses: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.1.0-beta1.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.1/ocaml-5.1.0~beta1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: - -```bash -opam update -opam switch create ocaml-variants.5.1.0~beta1+options -``` - -where `option_list` is a space-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: - -```bash -opam switch create 5.1.0~beta1+flambda+nffa ocaml-variants.5.1.0~beta1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2023-08-01-ocaml-5.1.rc1.md b/data/changelog/ocaml/2023-08-01-ocaml-5.1.rc1.md deleted file mode 100644 index ea9710e73f..0000000000 --- a/data/changelog/ocaml/2023-08-01-ocaml-5.1.rc1.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: OCaml 5.1.0 - First Release Candidate -description: First Release Candidate of OCaml 5.1.0 -tags: [ocaml] -changelog: | - ## Changes Since the Beta - - ### Bug Fix - - - [#12445](https://github.com/ocaml/ocaml/issues/12445): missing GC root registrations in `runtime/io.c` - (Gabriel Scherer, review by Xavier Leroy and Jeremy Yallop) - - ### Configuration Fix (openBSD) - - - [#12372](https://github.com/ocaml/ocaml/issues/12372): Pass option `-no-execute-only` to the linker for OpenBSD >= 7.3 - so that code sections remain readable, as needed for closure marshaling. - (Xavier Leroy and Anil Madhavapeddy, review by Anil Madhavapeddy and - Sébastien Hinderer) - - ### Tool Fix (ocamlmktop) - - * [#11745](https://github.com/ocaml/ocaml/issues/11745), [#12358](https://github.com/ocaml/ocaml/issues/12358): Debugger and toplevels: embed printer types rather than - reading their representations from `topdirs.cmi` at runtime. - This change also removes the ocamlmktop initialisation module introduced - in [#11382](https://github.com/ocaml/ocaml/issues/11382) which was no longer useful. - This change breaks toplevel scripts relying on the visibility of `Topdirs` - in the initial toplevel environment without loading `topfind`. - Since the opam default `.ocamlinit` file loads `topfind`, it is expected - that only scripts run with `ocaml -noinit` are affected. - For those scripts, accessing `Topdirs` now requires the `compiler-libs` - directory to be added to the toplevel search path with - ``` - #directory "+compiler-libs";; - ``` - as was already the case for the other modules in the toplevel interface - library. - (Sébastien Hinderer, review by Florian Angeletti, Nicolás Ojeda Bär, and - Gabriel Scherer) - - ### Documentation Changes - - - - [#12201](https://github.com/ocaml/ocaml/issues/12201): in the tutorial on modules, replace priority queue example by - a simpler example based on FIFO queues. - (Xavier Leroy, review by Anil Madhavapeddy and Nicolás Ojeda Bär). - - - [#12352](https://github.com/ocaml/ocaml/issues/12352): Fix a typo in the documentation of Arg.write_arg - (Christophe Raffalli, review by Florian Angeletti) - ---- - - -The release of OCaml 5.1.0 is imminent. -As a final step, we are publishing a release candidate to check that everything is in order before the release in the upcoming week(s). - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -Compared to the beta release, this release contains one safe runtime fix and two configuration tweaks. - -The full change log for OCaml 5.1.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.1/Changes) -A short summary of the changes since the beta release is also available below. - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands on opam 2.1 and later: -```bash -opam update -opam switch create 5.1.0~rc1 -``` - -The source code for the release candidate is also directly available on: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.1.0-rc1.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.1/ocaml-5.1.0~rc1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: -```bash -opam update -opam switch create ocaml-variants.5.1.0~rc1+options -``` -where `` is a comma-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: -```bash -opam switch create 5.1.0~rc1+flambda+nffa ocaml-variants.5.1.0~rc1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2023-08-29-ocaml-5.1.rc2.md b/data/changelog/ocaml/2023-08-29-ocaml-5.1.rc2.md deleted file mode 100644 index 4fc80b5dac..0000000000 --- a/data/changelog/ocaml/2023-08-29-ocaml-5.1.rc2.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: OCaml 5.1.0 - Second Release Candidate -description: Second Release Candidate of OCaml 5.1.0 -tags: [ocaml] -changelog: | - ## Last Minute Bug Fixes - - ### Type System: - - * (*breaking change*) [#6941](https://github.com/ocaml/ocaml/issues/6941), [#11187](https://github.com/ocaml/ocaml/issues/11187), +[#12483](https://github.com/ocaml/ocaml/issues/12483): prohibit using classes through recursive modules - inheriting or including a class belonging to a mutually-recursive module - would previous behave incorrectly, and now results in a clean error. - (Leo White, review by Gabriel Scherer and Florian Angeletti) - - ### Runtime - - - [#12481](https://github.com/ocaml/ocaml/issues/12481), [#12505](https://github.com/ocaml/ocaml/issues/12505): Fix incorrect initialization of array expressions - `[|e1;...;eN|]` when `N` is large enough to require major heap allocation. - (Xavier Leroy, report by Andrey Popp, analysis by KC Sivaramakrishnan - and Vincent Laviron, review by Gabriel Scherer) - ---- -In the last two weeks, two significant bugs have been discovered in the release candidate for OCaml 5.1.0 (one affecting the type system, another in the runtime). - -Those bugs are now fixed and we are publishing a second release candidate to check that everything is in order before the release in the upcoming week. - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -The full changelog for OCaml 5.1.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.1/Changes). -A short summary of the two fixed bugs in this release candidate is also available below. - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands on opam 2.1 and later: -```bash -opam update -opam switch create 5.1.0~rc2 -``` - -The source code for the release candidate is also directly available on: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.1.0-rc2.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.1/ocaml-5.1.0~rc2.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: -```bash -opam update -opam switch create ocaml-variants.5.1.0~rc2+options -``` -where `` is a comma-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: -```bash -opam switch create 5.1.0~rc2+flambda+nffa ocaml-variants.5.1.0~rc2+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2023-09-06-ocaml-5.1.0.rc3.md b/data/changelog/ocaml/2023-09-06-ocaml-5.1.0.rc3.md deleted file mode 100644 index 85f57d326e..0000000000 --- a/data/changelog/ocaml/2023-09-06-ocaml-5.1.0.rc3.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: OCaml 5.1.0 - Third Release Candidate -description: Third Release Candidate of OCaml 5.1.0 -tags: [ocaml] -changelog: | - ## Last Second Bug Fixes - - [#11284](https://github.com/ocaml/ocaml/issues/11284), +[#12525](https://github.com/ocaml/ocaml/issues/12525): Use compression of entries scheme when pruning mark stack. - Can decrease memory usage for some workloads, otherwise should be - unobservable. - (Tom Kelly, review by Sabine Schmaltz, Sadiq Jaffer, and Damien Doligez) - - - [#12486](https://github.com/ocaml/ocaml/issues/12486): Fix delivery of unhandled effect exceptions on s390x - (Miod Vallat, report by Jan Midtgaard, review by Vincent Laviron and Xavier - Leroy) ---- - -Since last week, there were two significant bugs fixed in the OCaml 5.1.0 runtime (one overflow bug and a stack corruption bug in the s390x port). Since those bug fixes are as small as they are subtle, they were deemed worthy of a release of a third release candidate for OCaml 5.1.0. - -If there are no more surprises this week, the release of OCaml 5.1.0 shall happen next week. - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -The full changelog for OCaml 5.1.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.1/Changes) - -A short summary of the two fixed bugs in this release candidate is also available below. - - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands on opam 2.1 and later: -```bash -opam update -opam switch create 5.1.0~rc3 -``` - -The source code for the release candidate is also directly available on: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.1.0-rc3.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.1/ocaml-5.1.0~rc3.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: -```bash -opam update -opam switch create ocaml-variants.5.1.0~rc3+options -``` -where `` is a comma-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: -```bash -opam switch create 5.1.0~rc3+flambda+nffa ocaml-variants.5.1.0~rc3+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2023-12-1-ocaml-5.1.1.rc1.md b/data/changelog/ocaml/2023-12-1-ocaml-5.1.1.rc1.md deleted file mode 100644 index 324e2e2e22..0000000000 --- a/data/changelog/ocaml/2023-12-1-ocaml-5.1.1.rc1.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: OCaml 5.1.1 - First Release Candidate -description: First Release Candidate of OCaml 5.1.1 -tags: [ocaml] -changelog: | - ## Changes in OCaml 5.1.1 - - ### Standard Library Dependency Fix: - - * (*breaking change*) [#12562](https://github.com/ocaml/ocaml/issues/12562), [#12734](https://github.com/ocaml/ocaml/issues/12734), [#12783](https://github.com/ocaml/ocaml/issues/12783): Remove the `Marshal.Compression` flag to the - `Marshal.to_*` functions introduced in 5.1 by [#12006](https://github.com/ocaml/ocaml/issues/12006), as it cannot - be implemented without risking to link -lzstd with all - ocamlopt-generated executables. The compilers are still able to use - ZSTD compression for compilation artefacts. - (Xavier Leroy and David Allsopp, report by Kate Deplaix, review by - Nicolás Ojeda Bär, Kate Deplaix, and Damien Doligez). - - ### Type System Bug Fix: - - - [#12623](https://github.com/ocaml/ocaml/issues/12623), fix the computation of variance composition - (Florian Angeletti, report by Vesa Karvonen, review by Gabriel Scherer) - - ### GC Performance Regression Fixes - - - [#12590](https://github.com/ocaml/ocaml/issues/12590), [#12595](https://github.com/ocaml/ocaml/issues/12595): Move `caml_collect_gc_stats_sample` in - `caml_empty_minor_heap_promote` before barrier arrival. - (B. Szilvasy, review by Gabriel Scherer) - - - [#12318](https://github.com/ocaml/ocaml/issues/12318): GC: simplify the meaning of custom_minor_max_size: blocks with - out-of-heap memory above this limit are now allocated directly in - the major heap. - (Damien Doligez, report by Stephen Dolan, review by Gabriel Scherer) - - - [#12439](https://github.com/ocaml/ocaml/issues/12439): Finalize and collect dead custom blocks during minor collection - (Damien Doligez, review by Xavier Leroy, Gabriel Scherer and KC - Sivaramakrishnan) - - - - [#12491](https://github.com/ocaml/ocaml/issues/12491), [#12493](https://github.com/ocaml/ocaml/issues/12493), [#12500](https://github.com/ocaml/ocaml/issues/12500), [#12754](https://github.com/ocaml/ocaml/issues/12754): Do not change GC pace when creating - sub-arrays of bigarrays - (Xavier Leroy, report by Ido Yariv, analysis by Gabriel Scherer, - - ### Miscellaneous Bug Fixes - - - [#12581](https://github.com/ocaml/ocaml/issues/12581), [#12609](https://github.com/ocaml/ocaml/issues/12609): Fix error on uses of packed modules outside their pack - to correctly handle nested packs - (Vincent Laviron, report by Javier Chávarri, review by Pierre Chambart) - - - [#12757](https://github.com/ocaml/ocaml/issues/12757): Fix ocamlnat (native toplevel) by registering frametables correctly - (Stephen Dolan, Nick Barnes and Mark Shinwell, - review by Vincent Laviron and Sébastien Hinderer) - - - [#12645](https://github.com/ocaml/ocaml/issues/12645), [#12649](https://github.com/ocaml/ocaml/issues/12649) fix error messages for cyclic type definitions in presence of - the `-short-paths` flag. - (Florian Angeletti, report by Vesa Karvonen, review by Gabriel Scherer) - - ---- - -Two months (and half) after the release of OCaml 5.1.0, we have discovered three -significant regressions in OCaml 5.1.0, affecting the packaging of executables, -the typechecking of OCaml programs, and the performance of numerical codes. - -Since those regressions affect many users and could have lasting effects, we -have decided to cut a patch release of OCaml 5.1 with fixes for those issues -next week. - -To give time for opam packages to test this patch version, we -have just published a first release candidate for OCaml 5.1.1 . -The full list of changes in this release candidate is available below. - -As a major exception to our policy for patch releases, OCaml 5.1.1 will -contain one breaking change in the standard library: the `Compression` flag has -been removed from the `Marshal` module. -This drastic measure was taken because supporting zstd compression in the -standard library made zstd a dependency of all OCaml executables. Since the -compiler should not impose its dependency on end-users, the support for -compressed marshaling has been moved to a compiler internal library in 5.1.1. -This internally library might be released as an independent library in later -releases of OCaml but not in OCaml 5.1.1 to give us time to polish the library -integration and packaging. - - -Installation Instructions --------------------------- - -The base compiler can be installed as an opam switch with the following commands on opam 2.1 and later: - - opam update - opam switch create 5.1.1~rc1 - -The source code for the release candidate is also directly available on: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.1.1-rc1.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.1/ocaml-5.1.1~rc1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: - - opam update - opam switch create ocaml-variants.5.1.1~rc1+options - -where `option_list` is a space-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: - - opam switch create 5.1.1~rc1+flambda+nffa ocaml-variants.5.1.1~rc1+options ocaml-option-flambda ocaml-option-no-flat-float-array - -All available options can be listed with `opam search ocaml-option`. - diff --git a/data/changelog/ocaml/2024-02-05-ocaml-5.2.0-alpha1.md b/data/changelog/ocaml/2024-02-05-ocaml-5.2.0-alpha1.md deleted file mode 100644 index 9161102a80..0000000000 --- a/data/changelog/ocaml/2024-02-05-ocaml-5.2.0-alpha1.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: OCaml 5.2.0 - First Alpha -description: First Alpha Release of OCaml 5.2.0 -tags: [ocaml] ---- - -Two months after the release of OCaml 5.1.1, the set of new features for the -future version 5.2.0 of OCaml has been frozen. We are thus happy to announce the -first alpha release for OCaml 5.2.0. - -This alpha version is here to help fellow hackers join us early in our bug -hunting and opam ecosystem fixing fun (see below for the installation instructions). - -The progresses on stabilising the ecosystem are tracked on the -[opam readiness for 5.2.0 meta-issue](https://github.com/ocaml/opam-repository/issues/25182). -The full release is expected around April. - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -If you are interested in the ongoing list of new features and bug fixes, the -updated change log for OCaml 5.2.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.2/Changes). - - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands -on opam 2.1 and later: - -```bash -opam update -opam switch create 5.2.0~alpha1 -``` - -For previous version of opam, the switch creation command line is slightly more verbose: - -```bash -opam update -opam switch create 5.2.0~alpha1 --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` - -The source code for the alpha is also available at these addresses: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.2.0-alpha1.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.2/ocaml-5.2.0~alpha1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: - -```bash -opam update -opam switch create ocaml-variants.5.2.0~alpha1+options -``` - -where `option_list` is a space separated list of `ocaml-option-*` packages. For instance, for a flambda and no-flat-float-array switch: - -```bash -opam switch create 5.2.0~alpha1+flambda+nffa ocaml-variants.5.2.0~alpha1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -The command line above is slightly more complicated for opam version anterior to 2.1: - - -```bash -opam update -opam switch create --packages=ocaml-variants.5.2.0~alpha1+options, --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git -``` -In both cases, all available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2024-03-07-ocaml-4.14.2.rc1.md b/data/changelog/ocaml/2024-03-07-ocaml-4.14.2.rc1.md deleted file mode 100644 index 8c134247f7..0000000000 --- a/data/changelog/ocaml/2024-03-07-ocaml-4.14.2.rc1.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: OCaml 4.14.2 - Release Candidate -description: Release Candidate of OCaml 4.14.2 -tags: [ocaml] -changelog: | - ## Changes Since OCaml 4.14.1 - ### Runtime System: - - - [#11764](https://github.com/ocaml/ocaml/issues/11764), [#12577](https://github.com/ocaml/ocaml/issues/12577): Add prototypes to old-style C function definitions - and declarations. - (Antonin Décimo, review by Xavier Leroy and Nick Barnes) - - - [#11763](https://github.com/ocaml/ocaml/issues/11763), [#11759](https://github.com/ocaml/ocaml/issues/11759), [#11861](https://github.com/ocaml/ocaml/issues/11861), [#12509](https://github.com/ocaml/ocaml/issues/12509), [#12577](https://github.com/ocaml/ocaml/issues/12577): Use strict prototypes on primitives. - (Antonin Décimo, review by Xavier Leroy, David Allsopp, Sébastien - Hinderer and Nick Barnes) - - * (*breaking change*) [#10723](https://github.com/ocaml/ocaml/issues/10723): Do not use `-flat-namespace` linking for macOS. - (Carlo Cabrera, review by Damien Doligez) - - - [#11332](https://github.com/ocaml/ocaml/issues/11332), [#12702](https://github.com/ocaml/ocaml/issues/12702): Make sure `Bool_val(v)` has type `bool` in C++ - (Xavier Leroy, report by ygrek, review by Gabriel Scherer) - - ### Build System: - - - [#11590](https://github.com/ocaml/ocaml/issues/11590): Allow installing to a destination path containing spaces - (Élie Brami, review by Sébastien Hinderer and David Allsopp) - - - [#12372](https://github.com/ocaml/ocaml/issues/12372): Pass option `-no-execute-only` to the linker for OpenBSD >= 7.3 - so that code sections remain readable, as needed for closure marshaling. - (Xavier Leroy and Anil Madhavapeddy, review by Anil Madhavapeddy and - Sébastien Hinderer) - - - [#12903](https://github.com/ocaml/ocaml/issues/12903): Disable control flow integrity on OpenBSD >= 7.4 to avoid - illegal instruction errors on certain CPUs. - (Michael Hendricks, review by Miod Vallat) - - ### Bug fixes: - - - [#12061](https://github.com/ocaml/ocaml/issues/12061), [#12063](https://github.com/ocaml/ocaml/issues/12063): Don't add inconsistent equalities when computing - high-level error messages for functor applications and inclusions. - (Florian Angeletti, review by Gabriel Scherer) - - - [#12878](https://github.com/ocaml/ocaml/issues/12878): Fix incorrect treatment of injectivity for private recursive types. - (Jeremy Yallop, review by Gabriel Scherer and Jacques Garrigue) - - - [#12971](https://github.com/ocaml/ocaml/issues/12971), [#12974](https://github.com/ocaml/ocaml/issues/12974): Fix an uncaught Ctype. Escape exception on some - invalid programs forming recursive types. - (Gabriel Scherer, review by Florian Angeletti, report by Neven Villani) - - - [#12264](https://github.com/ocaml/ocaml/issues/12264), [#12289](https://github.com/ocaml/ocaml/issues/12289): Fix `compact_allocate` to avoid a pathological case - that causes very slow compaction. - (Damien Doligez, report by Arseniy Alekseyev, review by Sadiq Jaffer) - - - [#12513](https://github.com/ocaml/ocaml/issues/12513), [#12518](https://github.com/ocaml/ocaml/issues/12518): Automatically enable emulated `fma` for Visual Studio 2019+ - to allow configuration with either pre-Haswell/pre-Piledriver CPUs or running - in VirtualBox. Restores parity with the other Windows ports, which don't - require explicit `--enable-imprecise-c99-float-ops`. - (David Allsopp, report by Jonah Beckford and Kate Deplaix, review by - Sébastien Hinderer) - - - [#11633](https://github.com/ocaml/ocaml/issues/11633), [#11636](https://github.com/ocaml/ocaml/issues/11636): Bug fix in `caml_unregister_frametable` - (Frédéric Recoules, review by Gabriel Scherer) - - - [#12636](https://github.com/ocaml/ocaml/issues/12636), [#12646](https://github.com/ocaml/ocaml/issues/12646): More prudent reinitialisation of I/O mutexes after a fork() - (Xavier Leroy, report by Zach Baylin, review by Enguerrand Decorne) - - * (*breaking change*) [#10845](https://github.com/ocaml/ocaml/issues/10845) Emit frametable size on AMD64 BSD (OpenBSD, FreeBSD, NetBSD) systems - (emitted for Linux in [#8805](https://github.com/ocaml/ocaml/issues/8805)) - (Hannes Mehnert, review by Nicolás Ojeda Bär) - - - [#12958](https://github.com/ocaml/ocaml/issues/12958): Fix `tail-modulo-cons` compilation of `try-with`, `&&`, and `||` - expressions. - (Gabriel Scherer and Nicolás Ojeda Bär, report by Sylvain Boilard, review by - Gabriel Scherer) - - ---- - -The release of OCaml version 4.14.2 is imminent. - -OCaml 4.14.2 is a new update to the stable 4.14 branch of OCaml. This new -release backports many safe bug fixes from the OCaml 5 branch and fixes -a handful of compatibility issues of OCaml 4.14.1 with newer operating system versions. - -A full list of bug fixes is available below. - -In order to ensure that the future release works as expected, we are planning to test a release candidate during the upcoming week. - -If you find any bugs, please report them here on [GitHub](https://github.com/ocaml/ocaml/issues). - ----- - - -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands on opam 2.1: -``` -opam update -opam switch create 4.14.2~rc1 -``` - - -The source code for the release candidate is available on - -- [GitHub](https://github.com/ocaml/ocaml/archive/4.14.2-rc1.tar.gz) -- [Inria archives](https://caml.inria.fr/pub/distrib/ocaml-4.14/ocaml-4.14.2-rc1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: -```bash -opam update -opam switch create ocaml-variants.4.14.2~rc1+options -``` -where `` is a space-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: -```bash -opam switch create 4.14.2~rc1+flambda+nffa ocaml-variants.4.14.2~rc1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2024-03-15-ocaml-4.14.2.md b/data/changelog/ocaml/2024-03-15-ocaml-4.14.2.md deleted file mode 100644 index 6c6f6bf44b..0000000000 --- a/data/changelog/ocaml/2024-03-15-ocaml-4.14.2.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Release of OCaml 4.14.2 -description: Release of OCaml 4.14.2 -tags: [ocaml] -changelog: | - ## Changes in OCaml 4.14.2 (14 March 2024) - - ### Runtime system: - - - [#11764](https://github.com/ocaml/ocaml/issues/11764), [#12577](https://github.com/ocaml/ocaml/issues/12577): Add prototypes to old-style C function definitions - and declarations. - (Antonin Décimo, review by Xavier Leroy and Nick Barnes) - - - [#11763](https://github.com/ocaml/ocaml/issues/11763), [#11759](https://github.com/ocaml/ocaml/issues/11759), [#11861](https://github.com/ocaml/ocaml/issues/11861), [#12509](https://github.com/ocaml/ocaml/issues/12509), [#12577](https://github.com/ocaml/ocaml/issues/12577): Use strict prototypes on primitives. - (Antonin Décimo, review by Xavier Leroy, David Allsopp, Sébastien - Hinderer and Nick Barnes) - - * (*breaking change*) [#10723](https://github.com/ocaml/ocaml/issues/10723): do not use `-flat-namespace` linking for macOS. - (Carlo Cabrera, review by Damien Doligez) - - - [#11332](https://github.com/ocaml/ocaml/issues/11332), [#12702](https://github.com/ocaml/ocaml/issues/12702): make sure `Bool_val(v)` has type `bool` in C++ - (Xavier Leroy, report by ygrek, review by Gabriel Scherer) - - ### Build system: - - - [#11590](https://github.com/ocaml/ocaml/issues/11590): Allow installing to a destination path containing spaces. - (Élie Brami, review by Sébastien Hinderer and David Allsopp) - - - [#12372](https://github.com/ocaml/ocaml/issues/12372): Pass option -no-execute-only to the linker for OpenBSD >= 7.3 - so that code sections remain readable, as needed for closure marshaling. - (Xavier Leroy and Anil Madhavapeddy, review by Anil Madhavapeddy and - Sébastien Hinderer) - - - [#12903](https://github.com/ocaml/ocaml/issues/12903): Disable control flow integrity on OpenBSD >= 7.4 to avoid - illegal instruction errors on certain CPUs. - (Michael Hendricks, review by Miod Vallat) - - ### Bug fixes: - - - [#12061](https://github.com/ocaml/ocaml/issues/12061), [#12063](https://github.com/ocaml/ocaml/issues/12063): don't add inconsistent equalities when computing - high-level error messages for functor applications and inclusions. - (Florian Angeletti, review by Gabriel Scherer) - - - [#12878](https://github.com/ocaml/ocaml/issues/12878): fix incorrect treatment of injectivity for private recursive types. - (Jeremy Yallop, review by Gabriel Scherer and Jacques Garrigue) - - - [#12971](https://github.com/ocaml/ocaml/issues/12971), [#12974](https://github.com/ocaml/ocaml/issues/12974): fix an uncaught Ctype.Escape exception on some - invalid programs forming recursive types. - (Gabriel Scherer, review by Florian Angeletti, report by Neven Villani) - - - [#12264](https://github.com/ocaml/ocaml/issues/12264), [#12289](https://github.com/ocaml/ocaml/issues/12289): Fix compact_allocate to avoid a pathological case - that causes very slow compaction. - (Damien Doligez, report by Arseniy Alekseyev, review by Sadiq Jaffer) - - - [#12513](https://github.com/ocaml/ocaml/issues/12513), [#12518](https://github.com/ocaml/ocaml/issues/12518): Automatically enable emulated `fma` for Visual Studio 2019+ - to allow configuration with either pre-Haswell/pre-Piledriver CPUs or running - in VirtualBox. Restores parity with the other Windows ports, which don't - require explicit `--enable-imprecise-c99-float-ops`. - (David Allsopp, report by Jonah Beckford and Kate Deplaix, review by - Sébastien Hinderer) - - - [#11633](https://github.com/ocaml/ocaml/issues/11633), [#11636](https://github.com/ocaml/ocaml/issues/11636): bugfix in caml_unregister_frametable - (Frédéric Recoules, review by Gabriel Scherer) - - - [#12636](https://github.com/ocaml/ocaml/issues/12636), [#12646](https://github.com/ocaml/ocaml/issues/12646): More prudent reinitialization of I/O mutexes after a fork() - (Xavier Leroy, report by Zach Baylin, review by Enguerrand Decorne) - - * (*breaking change*) [#10845](https://github.com/ocaml/ocaml/issues/10845) Emit frametable size on amd64 BSD (OpenBSD, FreeBSD, NetBSD) systems - (emitted for Linux in [#8805](https://github.com/ocaml/ocaml/issues/8805)) - (Hannes Mehnert, review by Nicolás Ojeda Bär) - - - [#12958](https://github.com/ocaml/ocaml/issues/12958): Fix tail-modulo-cons compilation of try-with, && and || - expressions. - (Gabriel Scherer and Nicolás Ojeda Bär, report by Sylvain Boilard, review by - Gabriel Scherer) - - - [#12116](https://github.com/ocaml/ocaml/issues/12116), [#12993](https://github.com/ocaml/ocaml/issues/12993): explicitly build non PIE executables on x86 32bits - architectures - (Florian Angeletti, review by David Allsopp) - - - [#13018](https://github.com/ocaml/ocaml/issues/13018): Don't pass duplicate libraries to the linker when compiling ocamlc.opt - and when using systhreads (new versions of lld emit a warning). - (David Allsopp, review by Nicolás Ojeda Bär) ---- - -We have the pleasure of celebrating the birthday of Grace Chisholm Young by announcing the release of OCaml version 4.14.2. - -This release is a collection of safe bug fixes, cherry-picked from the OCaml 5 branch. -If you are still using OCaml 4.14 and cannot yet upgrade to OCaml 5, this release is for you. - -The 4.14 branch is expected to receive updates for at least one year, while the OCaml 5 branch is stabilising. - -Thus don't hesitate to report any bugs on the [OCaml issue tracker](https://github.com/ocaml/ocaml/issues). - -See the list of changes below for more details. - ---- - -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands: - -```bash -opam update -opam switch create 4.14.2 -``` -The source code for the release candidate is also directly available on: - -* [GitHub](https://github.com/ocaml/ocaml/archive/4.14.2.tar.gz) -* [Inria archive](https://caml.inria.fr/pub/distrib/ocaml-4.14/ocaml-4.14.2.tar.gz) diff --git a/data/changelog/ocaml/2024-03-25-ocaml-5.2.0-beta1.md b/data/changelog/ocaml/2024-03-25-ocaml-5.2.0-beta1.md deleted file mode 100644 index 6b072260ba..0000000000 --- a/data/changelog/ocaml/2024-03-25-ocaml-5.2.0-beta1.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: OCaml 5.2.0 - First Beta -description: First Beta Release of OCaml 5.2.0 -tags: [ocaml] -changelog: | - ### Runtime System Fixes - - - [#12875](https://github.com/ocaml/ocaml/issues/12875), [#12879](https://github.com/ocaml/ocaml/issues/12879), [#12882](https://github.com/ocaml/ocaml/issues/12882): Execute preemptive systhread switching as a - delayed pending action. This ensures that one can reason within the - FFI that no mutation happens on the same domain when allocating on - the OCaml heap from C, consistently with OCaml 4. This also fixes - further bugs with the multicore systhreads implementation. - (Guillaume Munch-Maccagnoni, bug reports and suggestion by Mark - Shinwell, review by Nick Barnes and Stephen Dolan) - - - [#12876](https://github.com/ocaml/ocaml/issues/12876): Port ThreadSanitizer support to Linux on POWER - (Miod Vallat, review by Tim McGilchrist) - - - [#12678](https://github.com/ocaml/ocaml/issues/12678), [#12898](https://github.com/ocaml/ocaml/issues/12898): free channel buffers on close rather than on finalization - (Damien Doligez, review by Jan Midtgaard and Gabriel Scherer, report - by Jan Midtgaard) - - - [#12915](https://github.com/ocaml/ocaml/issues/12915): Port ThreadSanitizer support to Linux on s390x - (Miod Vallat, review by Tim McGilchrist) - - - [#12914](https://github.com/ocaml/ocaml/issues/12914): Slightly change the s390x assembly dialect in order to build with - Clang's integrated assembler. - (Miod Vallat, review by Gabriel Scherer) - - - [#12897](https://github.com/ocaml/ocaml/issues/12897): fix locking bugs in Runtime_events - (Gabriel Scherer and Thomas Leonard, - review by Olivier Nicole, Vincent Laviron and Damien Doligez, - report by Thomas Leonard) - - - [#12860](https://github.com/ocaml/ocaml/issues/12860): Fix an assertion that wasn't taking into account the possibility of an - ephemeron pointing at static data. - (Mark Shinwell, review by Gabriel Scherer and KC Sivaramakrishnan) - - - [#11040](https://github.com/ocaml/ocaml/issues/11040), [#12894](https://github.com/ocaml/ocaml/issues/12894): Silence false data race observed between caml_shared_try_alloc - and oldify. Introduces macros to call tsan annotations which help annotate - a ``happens before'' relationship. - (Hari Hara Naveen S and Olivier Nicole, - review by Gabriel Scherer and Miod Vallat) - - - [#12919](https://github.com/ocaml/ocaml/issues/12919): Fix register corruption in caml_callback2_asm on s390x. - (Miod Vallat, review by Gabriel Scherer) - - - [#12969](https://github.com/ocaml/ocaml/issues/12969): Fix a data race in caml_darken_cont - (Fabrice Buoro and Olivier Nicole, review by Gabriel Scherer and Miod Vallat) - - ### Standard Library Fix - - - [#12677](https://github.com/ocaml/ocaml/issues/12677), [#12889](https://github.com/ocaml/ocaml/issues/12889): make Domain.DLS thread-safe - (Gabriel Scherer, review by Olivier Nicole and Damien Doligez, - report by Vesa Karvonen) - - ### Type System Fix - - - [#12924](https://github.com/ocaml/ocaml/issues/12924), [#12930](https://github.com/ocaml/ocaml/issues/12930): Rework package constraint checking to improve interaction with - immediacy - (Chris Casinghino and Florian Angeletti, review by Florian Angeletti and - Richard Eisenberg) - - ### Compiler User-Interface Fix - - - [#12971](https://github.com/ocaml/ocaml/issues/12971), [#12974](https://github.com/ocaml/ocaml/issues/12974): fix an uncaught Ctype.Escape exception on some - invalid programs forming recursive types. - (Gabriel Scherer, review by Florian Angeletti, report by Neven Villani) - - ### Build System Fixes - - - [#12198](https://github.com/ocaml/ocaml/issues/12198), [#12321](https://github.com/ocaml/ocaml/issues/12321), [#12586](https://github.com/ocaml/ocaml/issues/12586), [#12616](https://github.com/ocaml/ocaml/issues/12616), [#12706](https://github.com/ocaml/ocaml/issues/12706), +[#13048](https://github.com/ocaml/ocaml/issues/13048): continue the merge of the - sub-makefiles into the root Makefile started with [#11243](https://github.com/ocaml/ocaml/issues/11243), [#11248](https://github.com/ocaml/ocaml/issues/11248), - [#11268](https://github.com/ocaml/ocaml/issues/11268), [#11420](https://github.com/ocaml/ocaml/issues/11420) and [#11675](https://github.com/ocaml/ocaml/issues/11675). - (Sébastien Hinderer, review by David Allsopp and Florian Angeletti) - - - [#12768](https://github.com/ocaml/ocaml/issues/12768), +[#13030](https://github.com/ocaml/ocaml/issues/13030): Detect mingw-w64 coupling with GCC or LLVM, detect clang-cl, - and fix C compiler feature detection on macOS. - (Antonin Décimo, review by Miod Vallat and Sébastien Hinderer) - - - [#13019](https://github.com/ocaml/ocaml/issues/13019): Remove linking instructions for the Unix library from threads.cma - (this was done for threads.cmxa in OCaml 3.11). Eliminates warnings from - new lld when using threads.cma of duplicated libraries. - (David Allsopp, review by Nicolás Ojeda Bär) - - - [#12758](https://github.com/ocaml/ocaml/issues/12758), +[#12998](https://github.com/ocaml/ocaml/issues/12998): Remove the `Marshal.Compression` flag to the - `Marshal.to_*` functions. The compilers are still able to use - ZSTD compression for compilation artefacts. - This is a forward port and clean-up of the emergency fix that was introduced - - ### Compiler Internals Fix - - - [#12389](https://github.com/ocaml/ocaml/issues/12389), [#12544](https://github.com/ocaml/ocaml/issues/12544), [#12984](https://github.com/ocaml/ocaml/issues/12984), +[#12987](https://github.com/ocaml/ocaml/issues/12987): centralize the handling of metadata for - compilation units and artifacts in preparation for better unicode support for - OCaml source files. - (Florian Angeletti, review by Vincent Laviron and Gabriel Scherer) - - --- - -Nearly two months after the first alpha release, the release of OCaml 5.2.0 is drawing near. - -We have thus released a first beta version of OCaml 5.2.0 to help you update your softwares and libraries ahead of the release (see below for the installation instructions). - -Compared to the alpha release, this beta contains a majority of runtime system fixes, and a handful of other fixes across many subsystems. - -Overall, the opam ecosystem looks in a good shape for the first beta release. -Most core development tools support OCaml 5.2.0, and you can follow the last remaining wrinkles on the -[opam readiness for 5.2.0 meta-issue](https://github.com/ocaml/opam-repository/issues/25182). - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -Currently, the release is planned for the end of April or the beginning of May. - -If you are interested in full list of features and bug fixes of the new OCaml version, the -updated change log for OCaml 5.2.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.2/Changes). - - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands -on opam 2.1: - -```bash -opam update -opam switch create 5.2.0~beta1 -``` - -The source code for the alpha is also available at these addresses: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.2.0-beta1.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.2/ocaml-5.2.0~beta1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: - -```bash -opam update -opam switch create ocaml-variants.5.2.0~beta1+options -``` - -where `option_list` is a space-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: - -```bash -opam switch create 5.2.0~beta1+flambda+nffa ocaml-variants.5.2.0~beta1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2024-04-16-ocaml-5.2.0-beta2.md b/data/changelog/ocaml/2024-04-16-ocaml-5.2.0-beta2.md deleted file mode 100644 index 20135342b2..0000000000 --- a/data/changelog/ocaml/2024-04-16-ocaml-5.2.0-beta2.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: OCaml 5.2.0 - Second Beta -description: Second Beta Release of OCaml 5.2.0 -tags: [ocaml] -changelog: | - ### Compiler-libs API Changes - - - [#13001](https://github.com/ocaml/ocaml/issues/13001): do not read_back entire shapes to get aliases' uids when building the - usages index - (Ulysse Gérard, review by Gabriel Scherer and Nathanaëlle Courant) - - ### Bug Fixes - - - [#13058](https://github.com/ocaml/ocaml/issues/13058): Add TSan instrumentation to caml_call_gc(), since it may raise - exceptions. - (Fabrice Buoro, Olivier Nicole, Gabriel Scherer and Miod Vallat) - - - [#13079](https://github.com/ocaml/ocaml/issues/13079): Save and restore frame pointer across Iextcall on ARM64 - (Tim McGilchrist, review by KC Sivaramakrishnan and Miod Vallat) - - - [#13094](https://github.com/ocaml/ocaml/issues/13094): Fix undefined behavior of left-shifting a negative number. - (Antonin Décimo, review by Miod Vallat and Nicolás Ojeda Bär) - - ### Documentation Updates - - - [#13078](https://github.com/ocaml/ocaml/issues/13078): update Format tutorial on structural boxes to mention alignment - questions. - (Edwin Török, review by Florian Angeletti) - - - [#13092](https://github.com/ocaml/ocaml/issues/13092): document the existence of the `[@@poll error]` built-in attribute - (Florian Angeletti, review by Gabriel Scherer) - - - [#13066](https://github.com/ocaml/ocaml/issues/13066), update OCAMLRUNPARAM documentation for the stack size parameter l - (Florian Angeletti, review by Nicolás Ojeda Bär, Tim McGilchrist, and - Miod Vallat) - --- - -Last week, we merged an update to the compiler-libs "shape" API for querying definition information from the compiler. - -Unfortunately, this small change of API breaks compatibility with at least odoc. -Generally, we try to avoid this kind of changes during the beta releases of the -compiler. However, after discussions we concluded that it will be easier on the -long term to fix the API right now in order to avoid multiplying the number of -supported versions of the shape API in the various OCaml developer tools . - -We have thus released a second beta version of OCaml 5.2.0 to give the time to developer tools to update their 5.2.0 version ahead of the release (see below for the installation instructions). - -Beyond this changes of API, the new beta contains three more bug fixes and three -documentation updates, which is a good sign in term of stability. - -As usual, you can follow the last remaining compatibility slags on the -[opam readiness for 5.2.0 meta-issue](https://github.com/ocaml/opam-repository/issues/25182). - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -Currently, the release is planned for the beginning of May. - -If you are interested in full list of features and bug fixes of the new OCaml version, the -updated change log for OCaml 5.2.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.2/Changes). - - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands -on opam 2.1: - -```bash -opam update -opam switch create 5.2.0~beta2 -``` - -The source code for the beta is also available at these addresses: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.2.0-beta2.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.2/ocaml-5.2.0~beta2.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: - -```bash -opam update -opam switch create ocaml-variants.5.2.0~beta2+options -``` - -where `option_list` is a space-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: - -```bash -opam switch create 5.2.0~beta2+flambda+nffa ocaml-variants.5.2.0~beta2+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2024-05-02-ocaml-5.2.0.rc1.md b/data/changelog/ocaml/2024-05-02-ocaml-5.2.0.rc1.md deleted file mode 100644 index 3ee212f2b2..0000000000 --- a/data/changelog/ocaml/2024-05-02-ocaml-5.2.0.rc1.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: OCaml 5.2.0 - First Release Candidate -description: First Release Candidate of OCaml 5.2.0 -tags: [ocaml] -changelog: | - ## Changes since the second beta - - - [#13130](https://github.com/ocaml/ocaml/issues/13130): Minor fixes to `pprintast` for raw identifiers and local module open - syntax for types. - (Chet Murthy, review by Gabriel Scherer) - - - [#13100](https://github.com/ocaml/ocaml/issues/13100) Fix detection of `zstd` when compiling with `musl-gcc` - (David Allsopp, review by Samuel Hym) ---- - - -The release of OCaml 5.2.0 is imminent. -As a final step, we are publishing a release candidate to check that everything is in order before the release in the upcoming week(s). - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -Compared to the second beta, this release contains one small compiler-libs printer fix and one configuration tweak. - -The full change log for OCaml 5.2.0 is available [on -GitHub](https://github.com/ocaml/ocaml/blob/5.2/Changes). A short summary of the -changes since the second beta release is also available below. - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands on opam 2.1 and later: -```bash -opam update -opam switch create 5.2.0~rc1 -``` - -The source code for the release candidate is also directly available on: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.2.0-rc1.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.2/ocaml-5.2.0~rc1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: -```bash -opam update -opam switch create ocaml-variants.5.2.0~rc1+options -``` -where `` is a space-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: -```bash -opam switch create 5.2.0~rc1+flambda+nffa ocaml-variants.5.2.0~rc1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2024-09-20-ocaml-5.3.0.alpha1.md b/data/changelog/ocaml/2024-09-20-ocaml-5.3.0.alpha1.md deleted file mode 100644 index e4680d5648..0000000000 --- a/data/changelog/ocaml/2024-09-20-ocaml-5.3.0.alpha1.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: OCaml 5.3.0 - First Alpha -description: First Alpha Release of OCaml 5.3.0 -tags: [ocaml] ---- - -Four months after the release of OCaml 5.2.0, the set of new features for the -future version 5.3.0 of OCaml has been frozen. We are thus happy to announce the -first alpha release for OCaml 5.3.0. - -This alpha version is here to help fellow hackers join us early in our bug -hunting and opam ecosystem fixing fun (see below for the installation -instructions). More information about the whole release process is now available -in the [compiler -repository](https://github.com/ocaml/ocaml/blob/trunk/release-info/introduction.md), -and we will try to propagate this information to ocaml.org shortly. - - -The progresses on stabilising the ecosystem are tracked on the [opam readiness for 5.3.0 meta-issue](https://github.com/ocaml/opam-repository/issues/26596). - -The full release is expected around November, see the [new prospective -calendar](https://github.com/ocaml/ocaml/blob/trunk/release-info/calendar.md) -for more information. - -If you find any bugs, please report them on [OCaml's issue -tracker](https://github.com/ocaml/ocaml/issues). - -If you are interested in the ongoing list of new features and bug fixes, the -updated change log for OCaml 5.3.0 is available -[on GitHub](https://github.com/ocaml/ocaml/blob/5.3/Changes). - - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands -on opam 2.1 and later: - -```bash -opam update -opam switch create 5.3.0~alpha1 -``` - -The source code for the alpha is also available at these addresses: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.3.0-alpha1.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.3/ocaml-5.3.0~alpha1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: - -```bash -opam update -opam switch create ocaml-variants.5.3.0~alpha1+options -``` - -where `option_list` is a space separated list of `ocaml-option-*` packages. For instance, for a flambda and no-flat-float-array switch: - -```bash -opam switch create 5.3.0~alpha1+flambda+nffa ocaml-variants.5.3.0~alpha1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2024-10-31-ocaml-5.3.0.beta1.md b/data/changelog/ocaml/2024-10-31-ocaml-5.3.0.beta1.md deleted file mode 100644 index 048e922ea3..0000000000 --- a/data/changelog/ocaml/2024-10-31-ocaml-5.3.0.beta1.md +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: OCaml 5.3.0 - First Beta -description: First Beta Release of OCaml 5.3.0 -tags: [ocaml] -changelog: | - ### Runtime fixes - - - [#13502](https://github.com/ocaml/ocaml/issues/13502): Fix misindexing related to `Gc.finalise_last` that could prevent - finalisers from being run. - (Nick Roberts, review by Mark Shinwell) - - - [#13402](https://github.com/ocaml/ocaml/issues/13402), [#13512](https://github.com/ocaml/ocaml/issues/13512), [#13549](https://github.com/ocaml/ocaml/issues/13549), [#13553](https://github.com/ocaml/ocaml/issues/13553): Revise bytecode implementation of callbacks - so that it no longer produces dangling registered bytecode fragments. - (Xavier Leroy, report by Jan Midtgaard, analysis by Stephen Dolan, - review by Miod Vallat) - - - [#13520](https://github.com/ocaml/ocaml/issues/13520): Fix compilation of native-code version of systhreads. Bytecode fields - were being included in the thread descriptors. - (David Allsopp, review by Sébastien Hinderer and Miod Vallat) - - ### Typechecker fixes - - - [#13579](https://github.com/ocaml/ocaml/issues/13579), [#13583](https://github.com/ocaml/ocaml/issues/13583): Unsoundness involving non-injective types + gadts - (Jacques Garrigue, report by @v-gb, - review by Richard Eisenberg and Florian Angeletti) - - - [#13388](https://github.com/ocaml/ocaml/issues/13388), [#13540](https://github.com/ocaml/ocaml/issues/13540): raises an error message (and not an internal compiler error) - when two local substitutions are incompatible (for instance `module type - S:=sig end type t:=(module S)`) - (Florian Angeletti, report by Nailen Matschke, review by Gabriel Scherer, and - Leo White) - - ### Compiler flag - - - [#13471](https://github.com/ocaml/ocaml/issues/13471): add `-keywords ` flag to define the list of keywords - recognized by the lexer, for instance `-keywords 5.2` disable the `effect` - keyword. - (Florian Angeletti, review by Gabriel Scherer) - - ### Runtime event library fixes - - - [#13419](https://github.com/ocaml/ocaml/issues/13419): Fix memory bugs in runtime events system. - (B. Szilvasy and Nick Barnes, review by Miod Vallat, Nick Barnes, - Tim McGilchrist, and Gabriel Scherer) - - - [#13407](https://github.com/ocaml/ocaml/issues/13407): Add Runtime_events.EV_EMPTY_MINOR - (Thomas Leonard) - - - [#13522](https://github.com/ocaml/ocaml/issues/13522): Confirm runtime events ring is still active after callback. - (KC Sivaramakrishnan, review by Sadiq Jaffer and Miod Vallat) - - - [#13529](https://github.com/ocaml/ocaml/issues/13529): Do not write to event ring after going out of stw participant set. - (KC Sivaramakrishnan, review by Sadiq Jaffer) - - ### Documentation - - - [#13424](https://github.com/ocaml/ocaml/issues/13424): Fix `Gc.quick_stat` documentation to clarify that returned fields - `live_words`, `live_blocks`, `free_words`, and `fragments` are not zero. - (Jan Midtgaard, review by Damien Doligez and KC Sivaramakrishnan) - - - [#13440](https://github.com/ocaml/ocaml/issues/13440): Update documentation of `Gc.{control,get,set}` to reflect fields - not currently supported on OCaml 5. - (Jan Midtgaard, review by Gabriel Scherer) - - - [#13469](https://github.com/ocaml/ocaml/issues/13469), [#13474](https://github.com/ocaml/ocaml/issues/13474), [#13535](https://github.com/ocaml/ocaml/issues/13535): Document that [Hashtbl.create n] creates a hash table - with a default minimal size, even if [n] is very small or negative. - (Antonin Décimo, Nick Bares, report by Nikolaus Huber and Jan Midtgaard, - review by Florian Angeletti, Anil Madhavapeddy, Gabriel Scherer, - and Miod Vallat) - - ### Standard library internal fix - - - - [#13543](https://github.com/ocaml/ocaml/issues/13543): Remove some String-Bytes conversion from the stdlib to behave better - with js_of_ocaml - (Hugo Heuzard, review by Gabriel Scherer) - - ### Toplevel fix - - - - [#13263](https://github.com/ocaml/ocaml/issues/13263), [#13560](https://github.com/ocaml/ocaml/issues/13560): fix printing true and false in toplevel and error - messages (no more unexpected \#true) - (Florian Angeletti, report by Samuel Vivien, review by Gabriel Scherer) - - ### Compiler internals - - - [#13391](https://github.com/ocaml/ocaml/issues/13391), [#13551](https://github.com/ocaml/ocaml/issues/13551): fix a printing bug with `-dsource` when using - raw literal inside a locally abstract type constraint - (i.e. `let f: type \#for. ... `) - (Florian Angeletti, report by Nick Roberts, review by Richard Eisenberg) ---- - -One month and half after the release of the first alpha for OCaml 5.3.0, -the release of OCaml 5.3.0 is drawing near. - -The internal API of the compiler libraries has been frozen, and most core -developer tools support (or will support soon) the new version of the compiler. - -We have thus released a first beta version of OCaml 5.3.0 to help you update -your software and libraries ahead of the release (see below for the -installation instructions). More information about the whole release process is -now available in the [compiler repository](https://github.com/ocaml/ocaml/blob/trunk/release-info/introduction.md). - -Compared to the first alpha release, this beta contains a few runtime or -typechecker fixes, a handful of fixes for the runtime event library and other -miscellaneous fixes. - -Exceptionally, this beta release also introduces a new flag `-keywords` for the -compiler. This backward compatibility flag aims to help compiling old code that -are using `effect` as a normal identifier, now that `effect` is a keyword in the -new effect handler syntax. - -The progresses on stabilising the ecosystem are tracked on the [opam readiness for 5.3.0 meta-issue](https://github.com/ocaml/opam-repository/issues/26596). - -The full release is expected in the end of November or beginning of December, -see the [new prospective -calendar](https://github.com/ocaml/ocaml/blob/trunk/release-info/calendar.md) -for more information. - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -If you are interested in full list of features and bug fixes of the new OCaml -version, the updated change log for OCaml 5.3.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.3/Changes). - - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands -on opam 2.1 and later: - -```bash -opam update -opam switch create 5.3.0~beta1 -``` - -The source code for the beta is also available at these addresses: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.3.0-beta1.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.3/ocaml-5.3.0~beta1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: - -```bash -opam update -opam switch create ocaml-variants.5.3.0~beta1+options -``` - -where `option_list` is a space separated list of `ocaml-option-*` packages. For instance, for a flambda and no-flat-float-array switch: - -```bash -opam switch create 5.3.0~beta1+flambda+nffa ocaml-variants.5.3.0~beta1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2024-11-07-5.2.1-rc1.md b/data/changelog/ocaml/2024-11-07-5.2.1-rc1.md deleted file mode 100644 index fdbe2bc203..0000000000 --- a/data/changelog/ocaml/2024-11-07-5.2.1-rc1.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: OCaml 5.2.1 - Release Candidate -description: Release Candidate for OCaml 5.2.1 -tags: [ocaml] -changelog: | - ## Changes Since OCaml 5.2.0 - ### Runtime System: - - [#13207](https://github.com/ocaml/ocaml/issues/13207): Be sure to reload the register caching the exception handler in - `caml_c_call` and `caml_c_call_stack_args`, as its value may have been changed - if the OCaml stack is expanded during a callback. - (Miod Vallat, report by Vesa Karvonen, review by Gabriel Scherer and - Xavier Leroy) - - - [#13252](https://github.com/ocaml/ocaml/issues/13252): Rework register assignment in the interpreter code on m68k on Linux, - due to the %a5 register being used by GLIBC. - (Miod Vallat, report by Stéphane Glondu, review by Gabriel Scherer and - Xavier Leroy) - - - [#13268](https://github.com/ocaml/ocaml/issues/13268): Fix a call to test in `configure.ac` that was causing errors when - LDFLAGS contains several words. - (Stéphane Glondu, review by Miod Vallat) - - - [#13234](https://github.com/ocaml/ocaml/issues/13234), [#13267](https://github.com/ocaml/ocaml/issues/13267): Open runtime events file in read-write mode on ARMel - (ARMv5) systems due to atomic operations limitations on that - platform. - (Stéphane Glondu, review by Miod Vallat and Vincent Laviron) - - - [#13188](https://github.com/ocaml/ocaml/issues/13188): fix races in the FFI code coming from the use of `Int_val(...)` - on rooted values inside blocking questions / without the runtime lock. - (Calling `Int_val(...)` on non-rooted immediates is fine, but any - access to rooted values must be done outside blocking sections / - with the runtime lock.) - (Etienne Millon, review by Gabriel Scherer, Jan Midtgaard, Olivier Nicole) - - - [#13318](https://github.com/ocaml/ocaml/issues/13318): Fix regression in GC alarms, and fix them for Flambda. - (Guillaume Munch-Maccagnoni, report by Benjamin Monate, review by - Vincent Laviron and Gabriel Scherer) - - - [#13140](https://github.com/ocaml/ocaml/issues/13140): POWER back-end: fix issue with call to `caml_call_realloc_stack` - from a DLL - (Xavier Leroy, review by Miod Vallat) - - - [#13370](https://github.com/ocaml/ocaml/issues/13370): Fix a low-probability crash when calling `Gc.counters`. - (Demi Marie Obenour, review by Gabriel Scherer) - - - [#13402](https://github.com/ocaml/ocaml/issues/13402), [#13512](https://github.com/ocaml/ocaml/issues/13512), [#13549](https://github.com/ocaml/ocaml/issues/13549), [#13553](https://github.com/ocaml/ocaml/issues/13553): Revise bytecode implementation of callbacks - so that it no longer produces dangling registered bytecode fragments. - (Xavier Leroy, report by Jan Midtgaard, analysis by Stephen Dolan, - review by Miod Vallat) - - - [#13502](https://github.com/ocaml/ocaml/issues/13502): Fix misindexing related to `Gc.finalise_last` that could prevent - finalisers from being run. - (Nick Roberts, review by Mark Shinwell) - - - [#13520](https://github.com/ocaml/ocaml/issues/13520): Fix compilation of native-code version of systhreads. Bytecode fields - were being included in the thread descriptors. - (David Allsopp, review by Sébastien Hinderer and Miod Vallat) ---- - -The release of OCaml version 5.2.1 is imminent. - -OCaml 5.2.1 is a collection of safe but import runtime time bug fixes backported from the 5.3 branch of OCaml. The full list of bug fixes is available above. - -In order to ensure that the future release works as expected, we are planning to test a release candidate during the upcoming week. - -If you find any bugs, please report them here on [GitHub](https://github.com/ocaml/ocaml/issues). - ----- - - -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands on opam 2.1: -``` -opam update -opam switch create 5.2.1~rc1 -``` - - -The source code for the release candidate is available on - -- [GitHub](https://github.com/ocaml/ocaml/archive/5.2.1-rc1.tar.gz) -- [Inria archives](https://caml.inria.fr/pub/distrib/ocaml-5.2/ocaml-5.2.1-rc1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: -```bash -opam update -opam switch create ocaml-variants.5.2.1~rc1+options -``` -where `` is a space-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: -```bash -opam switch create 5.2.1~rc1+flambda+nffa ocaml-variants.5.2.1~rc1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2024-11-28-ocaml-5.3.0-beta2.md b/data/changelog/ocaml/2024-11-28-ocaml-5.3.0-beta2.md deleted file mode 100644 index 5aec1f219a..0000000000 --- a/data/changelog/ocaml/2024-11-28-ocaml-5.3.0-beta2.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: OCaml 5.3.0 - Second Beta -description: Second Beta Release of OCaml 5.3.0 -tags: [ocaml] -changelog: | - # Changes Since The First Beta - ## Type system fixes - - - [#13501](https://github.com/ocaml/ocaml/issues/13501): Regression on mutually recursive types caused by [#12180](https://github.com/ocaml/ocaml/issues/12180). - Resuscitate Typedecl.update_type. - (Jacques Garrigue and Takafumi Saikawa, review by Florian Angeletti, Richard - Eisenberg and Gabriel Scherer) - - - [#13495](https://github.com/ocaml/ocaml/issues/13495), [#13514](https://github.com/ocaml/ocaml/issues/13514): Fix typechecker crash while typing objects - (Jacques Garrigue, report by Nicolás Ojeda Bär, review by - Nicolas Ojeda Bär, Gabriel Scherer, Stephen Dolan, Florian Angeletti) - - - [#13598](https://github.com/ocaml/ocaml/issues/13598): Falsely triggered warning 56 [unreachable-case] - This was caused by unproper protection of the retyping function. - (Jacques Garrigue, report by Tõivo Leedjärv, review by Florian Angeletti) - - ## Configuration fixes - * (*breaking change*) [#12578](https://github.com/ocaml/ocaml/issues/12578), [#12589](https://github.com/ocaml/ocaml/issues/12589), [#13322](https://github.com/ocaml/ocaml/issues/13322), +[#13519](https://github.com/ocaml/ocaml/issues/13519): Use configured CFLAGS and CPPFLAGS *only* - during the build of the compiler itself. Do not use them when - compiling third-party C sources through the compiler. Flags for - compiling third-party C sources can still be specified at configure - time in the COMPILER_{BYTECODE,NATIVE}_{CFLAGS,CPPFLAGS} - configuration variables. - (Sébastien Hinderer, report by William Hu, review by David Allsopp) - - ## C++ header compatibility - - - [#13541](https://github.com/ocaml/ocaml/issues/13541), [#13591](https://github.com/ocaml/ocaml/issues/13591): Fix headers for C++ inclusion. - (Antonin Décimo, review by Nick Barnes, report by Kate Deplaix) - - - ## Compiler library bug fix - - - [#13603](https://github.com/ocaml/ocaml/issues/13603), [#13604](https://github.com/ocaml/ocaml/issues/13604): fix source printing in the presence of the escaped raw - identifier `\#mod`. - (Florian Angeletti, report by Chris Casinghino, review by Gabriel Scherer) ---- - -One month after the release of the first beta for OCaml 5.3.0, -we are releasing a second and hopefully last beta release for OCaml -5.3.0 . - -The most notable changes for this second beta are probably a handful of type -system bugfixes. In particular, those fixes revert a change of behaviour in the -first beta when pattern matching GADTs with non-injective type parameters. - -We also have a C++ header compatibility fix and the restoration of some -configuration variable in Makefiles for the sake of backward compatibility. - -Overall, the release is converging and we are expecting to have a first release -candidate around the middle of December. The progresses on stabilising the -ecosystem are tracked on the -[opam readiness for 5.3.0 meta-issue](https://github.com/ocaml/opam-repository/issues/26596). - -Meanwhile, the second beta release of OCaml 5.3.0 is here to help you update -your software and libraries ahead of the release (see below for the installation -instructions). - -The full release is expected before the end of December. - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -If you are interested in full list of features and bug fixes of the new OCaml -version, the updated change log for OCaml 5.3.0 is available [on GitHub](https://github.com/ocaml/ocaml/blob/5.3/Changes). - - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands -on opam 2.1 and later: - -```bash -opam update -opam switch create 5.3.0~beta2 -``` - -The source code for the beta is also available at these addresses: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.3.0-beta2.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.3/ocaml-5.3.0~beta2.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: - -```bash -opam update -opam switch create ocaml-variants.5.3.0~beta2+options -``` - -where `option_list` is a space separated list of `ocaml-option-*` packages. For instance, for a flambda and no-flat-float-array switch: - -```bash -opam switch create 5.3.0~beta2+flambda+nffa ocaml-variants.5.3.0~beta2+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/ocaml/2024-12-19-ocaml-5.3.0-rc1.md b/data/changelog/ocaml/2024-12-19-ocaml-5.3.0-rc1.md deleted file mode 100644 index 0545c0420b..0000000000 --- a/data/changelog/ocaml/2024-12-19-ocaml-5.3.0-rc1.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: OCaml 5.3.0 - First Release Candidate -description: First Release Candidate of OCaml 5.3.0 -tags: [ocaml] -changelog: | - ## Changes since the second beta - - ### Type system - - - [#13690](https://github.com/ocaml/ocaml/issues/13690): some type expressions were incorrectly not generalized (because they - were assigned to the wrong level pool) - - ### Documentation - - - [#13666](https://github.com/ocaml/ocaml/issues/13666): Rewrite parts of the example code around nested lists in Chapter 6 - (Polymorphism and its limitations -> Polymorphic recursion) giving the - "depth" function [in the non-polymorphically-recursive part of the example] - a much more sensible behavior; also fix a typo and some formatting. - (Frank Steffahn, review by Florian Angeletti) - - ### Compiler user-interface and warnings: - - - [#12084](https://github.com/ocaml/ocaml/issues/12084), +[#13669](https://github.com/ocaml/ocaml/issues/13669), +[#13673](https://github.com/ocaml/ocaml/issues/13673): Check link order when creating archive and when using - ocamlopt. ---- - - -The release of OCaml 5.3.0 is imminent. -As a final step, we are publishing a release candidate to check that everything is in order before the release in the upcoming week(s). - -If you find any bugs, please report them on [OCaml's issue tracker](https://github.com/ocaml/ocaml/issues). - -Compared to the second beta, this release candidate contains a regression fix in the type system (some type expressions were not generalized when they ought to be), one fix for the new check for dependency order at link time, and a manual update. - -The full change log for OCaml 5.3.0 is available [on -GitHub](https://github.com/ocaml/ocaml/blob/5.3/Changes). A short summary of the -changes since the second beta release is also available below. - ---- -## Installation Instructions - -The base compiler can be installed as an opam switch with the following commands on opam 2.1 and later: -```bash -opam update -opam switch create 5.3.0~rc1 -``` - -The source code for the release candidate is also directly available on: - -* [GitHub](https://github.com/ocaml/ocaml/archive/5.3.0-rc1.tar.gz) -* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.3/ocaml-5.3.0~rc1.tar.gz) - -### Fine-Tuned Compiler Configuration - -If you want to tweak the configuration of the compiler, you can switch to the option variant with: -```bash -opam update -opam switch create ocaml-variants.5.3.0~rc1+options -``` -where `` is a space-separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: -```bash -opam switch create 5.3.0~rc1+flambda+nffa ocaml-variants.5.3.0~rc1+options ocaml-option-flambda ocaml-option-no-flat-float-array -``` - -All available options can be listed with `opam search ocaml-option`. diff --git a/data/changelog/opam-publish/2018-04-12-opam-publish-2.0.0~beta.md b/data/changelog/opam-publish/2018-04-12-opam-publish-2.0.0~beta.md deleted file mode 100644 index 530c51180a..0000000000 --- a/data/changelog/opam-publish/2018-04-12-opam-publish-2.0.0~beta.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: Opam-publish 2.0.0~beta -tags: [opam-publish, platform] -changelog: | - * Now based on opam 2 libs and intended for publications in the 2.0 format - (inclusive opam files, etc.) - * Bumped version number to avoid confusion with opam versions - * Removed the two-step operation ("prepare" and "publish"). A single invocation - does all - * Removed looking up current opam pinnings and repositories for metadata, which - was too complex and counter-intuitive. Now opam files are looked up only in - the specified directories or archives - * Multiple publications without added complexity - * Simplified command-line: URLs, directories, opam files, package names can be - specified directly on the command-line, and repeated for multiple - publications - * Allow providing the auth token directly ---- - diff --git a/data/changelog/opam/2013-09-20-opam-1-1-0-beta.md b/data/changelog/opam/2013-09-20-opam-1-1-0-beta.md deleted file mode 100644 index e72de6c1a5..0000000000 --- a/data/changelog/opam/2013-09-20-opam-1-1-0-beta.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: "OPAM 1.1.0 beta released" -authors: [ "Thomas Gazagnaire" ] -description: "Release announcement for OPAM 1.1.0~beta" -tags: [opam, platform] -changelog: | - * Automatic backup before any operation which might alter the list of installed packages - * Support for arbitrary sub-directories for metadata repositories - * Lots of colors - * New option `opam update -u` equivalent to `opam update && opam upgrade --yes` - * New `opam-admin` tool, bundling the features of `opam-mk-repo` and - `opam-repo-check` + new 'opam-admin stats' tool - * New `available`: field in opam files, superseding `ocaml-version` and `os` fields - * Package names specified on the command-line are now understood - case-insensitively (#705) - * Fixed parsing of malformed opam files (#696) - * Fixed recompilation of a package when uninstalling its optional dependencies (#692) - * Added conditional post-messages support, to help users when a package fails to - install for a known reason (#662) - * Rewrite the code which updates pin et dev packages to be quicker and more reliable - * Add {opam,url,desc,files/} overlay for all packages - * `opam config env` now detects the current shell and outputs a sensible default if - no override is provided. - * Improve `opam pin` stability and start display information about dev revisions - * Add a new `man` field in `.install` files - * Support hierarchical installation in `.install` files - * Add a new `stublibs` field in `.install` files - * OPAM works even when the current directory has been deleted - * speed-up invocation of `opam config var VARIABLE` when variable is simple - (eg. `prefix`, `lib`, ...) - * `opam list` now display only the installed packages. Use `opam list -a` to get - the previous behavior. - * Inverse the depext tag selection (useful for `ocamlot`) - * Add a `--sexp` option to `opam config env` to load the configuration under emacs - * Purge `~/.opam/log` on each invocation of OPAM - * System compiler with versions such as `version+patches` are now handled as if this - was simply `version` - * New `OpamVCS` functor to generate OPAM backends - * More efficient `opam update` - * Switch license to LGPL with linking exception - * `opam search` now also searches through the tags - * minor API changes for `API.list` and `API.SWITCH.list` - * Improve the syntax of filters - * Add a `messages` field - * Add a `--jobs` command line option and add `%{jobs}%` to be used in OPAM files - * Various improvements in the solver heuristics - * By default, turn-on checking of certificates for downloaded dependency archives - * Check the md5sum of downloaded archives when compiling OPAM - * Improved `opam info` command (more information, non-zero error code when no patterns match) - * Display OS and OPAM version on internal errors to ease error reporting - * Fix `opam reinstall` when reinstalling a package wich is a dependency of installed packages - * Export and read `OPAMSWITCH` to be able to call OPAM in different switches - * `opam-client` can now be used in a toplevel - * `-n` now means `--no-setup` and not `--no-checksums` anymore - * Fix support of FreeBSD - * Fix installation of local compilers with local paths endings with `../ocaml/` - * Fix the contents of `~/.opam/opam-init/variable.sh` after a switch ---- - -We are very happy to announce the **beta release** of OPAM version 1.1.0! - -OPAM is a source-based package manager for OCaml. It supports multiple -simultaneous compiler installations, flexible package constraints, and -a Git-friendly development workflow which. OPAM is edited and -maintained by OCamlPro, with continuous support from OCamlLabs and the -community at large (including its main industrial users such as -Jane-Street and Citrix). - -Since its first official release [last March][1], we have fixed many -bugs and added lots of [new features and stability improvements][2]. New -features go from more metadata to the package and compiler -descriptions, to improved package pin workflow, through a much faster -update algorithm. The full changeset is included below. - -We are also delighted to see the growing number of contributions from -the community to both OPAM itself (35 contributors) and to its -metadata repository (100+ contributors, 500+ unique packages, 1500+ -packages). It is really great to also see alternative metadata -repositories appearing in the wild (see for instance the repositories -for [Android][3], [Windows][4] and [so on][5]). To be sure that the -community efforts will continue to benefit to everyone and to -underline our committment to OPAM, we are rehousing it at -`https://opam.ocaml.org` and switching the license to CC0 (see [issue #955][6], -where 85 people are commenting on the thread). - -The binary installer has been updated for OSX and x86_64: -- http://www.ocamlpro.com/pub/opam_installer.sh - -You can also get the new version either from Anil's unstable PPA: - add-apt-repository ppa:avsm/ppa-testing - apt-get update - sudo apt-get install opam - -or build it from sources at : -- http://www.ocamlpro.com/pub/opam-full-1.1.0-beta.tar.gz -- https://github.com/OCamlPro/opam/releases/tag/1.1.0-beta - -NOTE: If you upgrade from OPAM 1.0, the first time you will run the -new `opam` binary it will upgrade its internal state in an incompatible -way: THIS PROCESS CANNOT BE REVERTED. We have tried hard to make this -process fault-resistant, but failures might happen. In case you have -precious data in your `~/.opam` folder, it is advised to **backup that -folder before you upgrade to 1.1**. - -[1]: http://www.ocamlpro.com/blog/2013/03/14/opam-1.0.0.html -[2]: https://github.com/OCamlPro/opam/issues?milestone=17&page=1&state=closed -[3]: https://github.com/vouillon/opam-android-repository -[4]: https://github.com/vouillon/opam-windows-repository -[5]: https://github.com/search?q=opam-repo&type=Repositories&ref=searchresults -[6]: https://github.com/OCamlPro/opam-repository/issues/955 diff --git a/data/changelog/opam/2013-10-14-opam-1-1-0-release-candidate.md b/data/changelog/opam/2013-10-14-opam-1-1-0-release-candidate.md deleted file mode 100644 index 9ae51b14f6..0000000000 --- a/data/changelog/opam/2013-10-14-opam-1-1-0-release-candidate.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "OPAM 1.1.0 release candidate out" -authors: [ "Louis Gesbert" ] -description: "Release announcement for OPAM 1.1.0~rc1" -tags: [opam, platform] -changelog: | - Too many to list here, see - [https://raw.github.com/OCamlPro/opam/1.1.0-RC/CHANGES](https://raw.github.com/OCamlPro/opam/1.1.0-RC/CHANGES) - - For packagers, some new fields have appeared in the OPAM description format: - - `depexts` provides facilities for dealing with system (non ocaml) - dependencies - - `messages`, `post-messages` can be used to notify the user or help her troubleshoot at package installation. - - `available` supersedes `ocaml-version` and `os` constraints, and can contain - more expressive formulas ---- - -**OPAM 1.1.0 is ready**, and we are shipping a release candidate for -packagers and all interested to try it out. - -This version features several bug-fixes over the September beta release, and -quite a few stability and usability improvements. Thanks to all beta-testers -who have taken the time to file reports, and helped a lot tackling the -remaining issues. - -## Repository change to opam.ocaml.org - -This release is synchronized with the migration of the main repository from -ocamlpro.com to ocaml.org. A redirection has been put in place, so that all -up-to-date installation of OPAM should be redirected seamlessly. -OPAM 1.0 instances will stay on the old repository, so that they won't be -broken by incompatible package updates. - -We are very happy to see the impressive amount of contributions to the OPAM -repository, and this change, together with the licensing of all metadata under -CC0 (almost pubic domain), guarantees that these efforts belong to the -community. - -# If you are upgrading from 1.0 - -The internal state will need to be upgraded at the first run of OPAM 1.1.0. -THIS PROCESS CANNOT BE REVERTED. We have tried hard to make it fault- -resistant, but failures might happen. In case you have precious data in your -`~/.opam folder`, it is advised to **backup that folder before you upgrade to 1.1.0**. - -## Installing - -Using the binary installer: -- download and run http://www.ocamlpro.com/pub/opam_installer.sh - -You can also get the new version either from Anil's unstable PPA: - add-apt-repository ppa:avsm/ppa-testing - apt-get update - sudo apt-get install opam - -or build it from sources at : -- http://www.ocamlpro.com/pub/opam-full-1.1.0.tar.gz -- https://github.com/OCamlPro/opam/releases/tag/1.1.0-RC diff --git a/data/changelog/opam/2014-08-14-opam-1-2-0-beta4.md b/data/changelog/opam/2014-08-14-opam-1-2-0-beta4.md deleted file mode 100644 index 974ab58106..0000000000 --- a/data/changelog/opam/2014-08-14-opam-1-2-0-beta4.md +++ /dev/null @@ -1,290 +0,0 @@ ---- -title: "OPAM 1.2.0 public beta released" -authors: [ "OCaml Platform Team" ] -description: "Release announcement for OPAM 1.2.0~beta" -tags: [opam, platform] ---- - -It has only been 18 months since the first release of OPAM, but it is already -difficult to remember a time when we did OCaml development without it. OPAM -has helped bring together much of the open-source code in the OCaml community -under a single umbrella, making it easier to discover, depend on, and maintain -OCaml applications and libraries. We have seen steady growth in the number -of new packages, updates to existing code, and a diverse group of contributors. - - -OPAM has turned out to be more than just another package manager. It is also -increasingly central to the demanding workflow of industrial OCaml development, -since it supports multiple simultaneous (patched) compiler installations, -sophisticated package version constraints that ensure statically-typed code can -be recompiled without conflict, and a distributed workflow that integrates -seamlessly with Git, Mercurial or Darcs version control. OPAM tracks multiple -revisions of a single package, thereby letting packages rely on older -interfaces if they need to for long-term support. It also supports multiple -package repositories, letting users blend the global stable package set with -their internal revisions, or building completely isolated package universes for -closed-source products. - -Since its initial release, we have been learning from the extensive feedback -from our users about how they use these features as part of their day-to-day -workflows. Larger projects like [XenAPI][xapi], the [Ocsigen][] web suite, -and the [Mirage OS][mir-www] publish OPAM [remotes][opam-remote] that build -their particular software suites. -Complex applications such as the [Pfff][] static analysis tool and [Hack][] -language from Facebook, the [Frenetic][] SDN language and the [Arakoon][] -distributed key store have all appeared alongside these libraries. -[Jane Street](https://www.janestreet.com) pushes regular releases of their -production [Core/Async](http://janestreet.github.io/) suite every couple -of weeks. - -One pleasant side-effect of the growing package database has been the -contribution of tools from the community that make the day-to-day use of OCaml -easier. These include the [utop][] interactive toplevel, the [IOCaml][] -browser notebook, and the [Merlin][] IDE extension. While these tools are an -essential first step, there's still some distance to go to make the OCaml -development experience feel fully integrated and polished. - -Today, we are kicking off the next phase of evolution of OPAM and starting the -journey towards building an *OCaml Platform* that combines the OCaml compiler -toolchain with a coherent workflow for build, documentation, testing and IDE -integration. As always with OPAM, this effort has been a collaborative effort, -coordinated by the [OCaml Labs][ocl-www] group in Cambridge and -[OCamlPro][ocp-www] in France. -The OCaml Platform builds heavily on OPAM, since it forms the substrate that -pulls together the tools and facilitates a consistent development workflow. -We've therefore created this blog on [opam.ocaml.org][] to chart its progress, -announce major milestones, and eventually become a community repository of all -significant activity. - -Major points: - -* **OPAM 1.2 beta available**: - Firstly, we're announcing **the availability of the OPAM 1.2 beta**, - which includes a number of new features, hundreds of bug fixes, and pretty - new colours in the CLI. We really need your feedback to ensure a polished - release, so please do read the release notes below. - -* In the coming weeks, we will provide an overview of what the OCaml Platform is - (and is not), and describe an example workflow that the Platform can enable. - -* **Feedback**: If you have questions or comments as you read these posts, - then please do join the [platform@lists.ocaml.org][platform-list] and make - them known to us. - - -[xapi]: http://wiki.xen.org/wiki/XAPI -[Ocsigen]: http://ocsigen.org -[mir-www]: http://openmirage.org -[opam-remote]: https://opam.ocaml.org/doc/Advanced_Usage.html#Handlingofrepositories -[bunzli-remote]: http://erratique.ch/software/opam/unreleased/ -[mottl-sw]: http://www.ocaml.info/software.html -[Pfff]: https://github.com/facebook/pfff/wiki/Main -[Hack]: https://code.facebook.com/posts/264544830379293/hack-a-new-programming-language-for-hhvm/ -[Frenetic]: https://github.com/frenetic-lang/frenetic -[Arakoon]: http://arakoon.org -[utop]: https://github.com/diml/utop -[IOCaml]: https://github.com/andrewray/iocaml -[Merlin]: https://github.com/the-lambda-church/merlin -[ocl-www]: http://www.cl.cam.ac.uk/projects/ocamllabs/ -[ocp-www]: http://www.ocamlpro.com -[opam.ocaml.org]: https://opam.ocaml.org -[platform-list]: https://lists.ocaml.org/listinfo/platform - - -## Releasing the OPAM 1.2 beta4 - -We are proud to announce the latest beta of OPAM 1.2. It comes packed with -[new features][gh-features-12], stability and usability improvements. Here the -highlights. - -### Binary RPMs and DEBs! - -We now have binary packages available for Fedora 19/20, CentOS 6/7, RHEL7, -Debian Wheezy and Ubuntu! You can see the full set at the [OpenSUSE Builder][suse] site and -[download instructions][suse-dl] for your particular platform. - -An OPAM binary installation doesn't need OCaml to be installed on the system, so you -can initialize a fresh, modern version of OCaml on older systems without needing it -to be packaged there. -On CentOS 6 for example: - -``` -cd /etc/yum.repos.d/ -wget http://download.opensuse.org/repositories/home:ocaml/CentOS_6/home:ocaml.repo -yum install opam -opam init --comp=4.01.0 -``` - -[suse]: https://build.opensuse.org/package/show/home:ocaml/opam# -[suse-dl]: http://software.opensuse.org/download.html?project=home:ocaml&package=opam - - -### Simpler user workflow - -For this version, we focused on improving the user interface and workflow. OPAM -is a complex piece of software that needs to handle complex development -situations. This implies things might go wrong, which is precisely when good -support and error messages are essential. OPAM 1.2 has much improved stability -and error handling: fewer errors and more helpful messages plus better state backups -when they happen. - -In particular, a clear and meaningful explanation is extracted from the solver -whenever you are attempting an impossible action (unavailable package, -conflicts, etc.): - -``` -$ opam install mirage-www=0.3.0 -The following dependencies couldn't be met: - - mirage-www -> cstruct < 0.6.0 - - mirage-www -> mirage-fs >= 0.4.0 -> cstruct >= 0.6.0 -Your request can't be satisfied: - - Conflicting version constraints for cstruct -``` - -This sets OPAM ahead of many other package managers in terms of -user-friendliness. Since this is made possible using the tools from -[irill][irill] (which are also used for [Debian][debian-weather]), we hope that -this work will find its way into other package managers. -The extra analyses in the package solver interface are used to improve the -health of the central package repository, via the [OPAM Weather service][ows]. - -And in case stuff does go wrong, we added the `opam upgrade --fixup` -command that will get you back to the closest clean state. - -The command-line interface is also more detailed and convenient, polishing and -documenting the rough areas. Just run `opam --help` to see the -manual page for the below features. - -* More expressive queries based on dependencies. - - ``` - $ opam list --depends-on cow --rec - # Available packages recursively depending on cow.0.10.0 for 4.01.0: - cowabloga 0.0.7 Simple static blogging support. - iocaml 0.4.4 A webserver for iocaml-kernel and iocamljs-kernel. - mirage-www 1.2.0 Mirage website (written in Mirage) - opam2web 1.3.1 (pinned) A tool to generate a website from an OPAM repository - opium 0.9.1 Sinatra like web toolkit based on Async + Cohttp - stone 0.3.2 Simple static website generator, useful for a portfolio or documentation pages - ``` - -* Check on existing `opam` files to base new packages from. - - ``` - $ opam show cow --raw - opam-version: "1" - name: "cow" - version: "0.10.0" - [...] - ``` - -* Clone the source code for any OPAM package to modify or browse the interfaces. - - ``` - $ opam source cow - Downloading archive of cow.0.10.0... - [...] - $ cd cow.0.10.0 - ``` - -We've also improved the general speed of the tool to cope with the much bigger -size of the central repository, which will be of importance for people building -on low-power ARM machines, and added a mechanism that will let you install -newer releases of OPAM directly from OPAM if you choose so. - - -### Yet more control for the packagers - -Packaging new libraries has been made as straight-forward as possible. -Here is a quick overview, you may also want to check the [OPAM 1.2 pinning][opam-1-2-pin] post. - -``` -opam pin add -``` - -will generate a new package on the fly by detecting the presence of an `opam` -file within the source repository itself. We'll do a followup post next week -with more details of this extended `opam pin` workflow. - -The package description format has also been extended with some new fields: - -* `bug-reports:` and `dev-repo:` add useful URLs -* `install:` allows build and install commands to be split, -* `flags:` is an entry point for several extensions that can affect your package. - -Packagers can limit dependencies in scope by adding one -of the keywords `build`, `test` or `doc` in front of their constraints: - -```opam -depends: [ - "ocamlfind" {build & >= 1.4.0} - "ounit" {test} -] -``` - -Here you don't specifically require `ocamlfind` at runtime, so changing it -won't trigger recompilation of your package. `ounit` is marked as only required -for the package's `build-test:` target, _i.e._ when installing with -`opam install -t`. This will reduce the amount of (re)compilation required -in day-to-day use. - -We've also made optional dependencies more consistent by _removing_ version -constraints from the `depopts:` field: their meaning was [unclear][opam200] and confusing. -The `conflicts` field is used to indicate versions of the optional dependencies -that are incompatible with your package to remove all ambiguity: - -```opam -depopts: [ "async" {>= "109.15.00"} & "async_ssl" {>= "111.06.00"} ] -``` - -becomes: - -```opam -depopts: [ "async" "async_ssl" ] -conflicts: [ "async" {< "109.15.00"} - "async_ssl" {< "111.06.00"} ] -``` - -There is an [upcoming `features` field][features-pr] that will give more -flexibility in a clearer and consistent way for such complex cases. - - -### Easier to package and install - -Efforts were made on the build of OPAM itself as well to make it as easy as possible -to compile, bootstrap or install. There is no more dependency on camlp4 (which has -been moved out of the core distribution in OCaml 4.02.0), and the build process -is more conventional (get the source, run `./configure`, `make lib-ext` to get the few -internal dependencies, `make` and `make install`). Packagers can use `make cold` -to build OPAM with a locally compiled version of OCaml (useful for platforms where -it isn't packaged), and also use `make download-ext` to store all the external archives -within the source tree (for automated builds which forbid external net access). - -The [whole documentation][opam12-doc] has been rewritten as well, to be better focused and -easier to browse. Please leave any feedback or changes on the documentation on the -[issue tracker](https://github.com/ocaml/opam/issues). - - -### Try it out ! - -The [public beta of OPAM 1.2][opam12-beta] is just out. You're welcome to give it a try and -give us feedback before we roll out the release! - -We'd be most interested on feedback on how easily you can work with the new -pinning features, on how the new metadata works for you... and on any errors you -may trigger that aren't followed by informative messages or clean behaviour. - -If you are hosting a repository, the [administration scripts][opam-admin-scripts] may help you quickly update all your packages to -benefit from the new features. - - -[opam12-beta]: https://github.com/ocaml/opam/releases/tag/1.2.0-beta4 "Opam 1.2-beta4 release" -[gh-features-12]: https://github.com/ocaml/opam/issues?q=label%3A%22Feature+Wish%22+milestone%3A1.2+is%3Aclosed "Features added in 1.2 from the tracker on Github" -[irill]: http://www.irill.org "IRILL" -[debian-weather]: https://qa.debian.org/dose/debcheck/testing_main/ "Debian Weather Service" -[ows]: http://ows.irill.org "The OPAM Weather Service" -[features-pr]: https://github.com/ocaml/opam/pull/1325 "PR for preliminary 'features' feature on Github" -[opam12-doc]: https://opam.ocaml.org/doc "Preview of documentation for OPAM 1.2" -[opam-admin-scripts]: https://github.com/ocaml/opam/tree/master/admin-scripts "Opam admin scripts directory on Github" -[opam200]: https://github.com/ocaml/opam/issues/200 -[opam-1-2-pin]: ../opam-1-2-pin "Blog post on OPAM Pin" diff --git a/data/changelog/opam/2016-09-20-opam-2-0-preview.md b/data/changelog/opam/2016-09-20-opam-2-0-preview.md deleted file mode 100644 index c79d3c1375..0000000000 --- a/data/changelog/opam/2016-09-20-opam-2-0-preview.md +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: "opam 2.0 preview release!" -authors: [ "Louis Gesbert" ] -description: "Release announcement for opam 2.0.0~preview" -tags: [opam, platform] ---- - - - -We are pleased to announce a preview release for opam 2.0, with over 700 -patches since [1.2.2](https://opam.ocaml.org/blog/opam-1-2-2-release/). Version -[2.0~alpha4](https://github.com/ocaml/opam/releases/2.0-alpha4) has just been -released, and is ready to be more widely tested. - -This version brings many new features and changes, the most notable one being -that OCaml compiler packages are no longer special entities, and are replaced -by standard package definition files. This in turn means that opam users have -more flexibility in how switches are managed, including for managing non-OCaml -environments such as [Coq](https://web.archive.org/web/20170410035834/http://coq.io/opam) using the same familiar tools. - -## A Few Highlights - -This is just a sample, see the full -[changelog](https://github.com/ocaml/opam/blob/2.0-alpha4/CHANGES) for more: - -- **Sandboxed builds:** Command wrappers can be configured to, for example, - restrict permissions of the build and install processes using Linux - namespaces, or run the builds within Docker containers. - -- **Compilers as packages:** This brings many advantages for opam workflows, - such as being able to upgrade the compiler in a given switch, better tooling for - local compilers, and the possibility to define `coq` as a compiler or even - use opam as a generic shell scripting engine with dependency tracking. - -- **Local switches:** Create switches within your projects for easier - management. Simply run `opam switch create ` to get - started. - -- **Inplace build:** Use opam to build directly from - your source directory. Ensure the package is pinned locally then run `opam - install --inplace-build`. - -- **Automatic file tracking:**: opam now tracks the files installed by packages - and is able to cleanly remove them when no existing files were modified. - The `remove:` field is now optional as a result. - -- **Configuration file:** This can be used to direct choices at `opam init` - automatically (e.g. specific repositories, wrappers, variables, fetch - commands, or the external solver). This can be used to override all of opam's - OCaml-related settings. - -- **Simpler library:** the OCaml API is completely rewritten and should make it - much easier to write external tools and plugins. Existing tools will need to be - ported. - -- **Better error mitigation:** Through clever ordering of the shell actions and - separation of `build` and `install`, most build failures can keep your current - installation intact, not resulting in removed packages anymore. - -## Roll out - -You are very welcome to try out the alpha, and report any issues. The repository -at `opam.ocaml.org` will remain in 1.2 format (with a 2.0 mirror at -`opam.ocaml.org/2.0~dev` in sync) until after the release is out, which means -the extensions can not be used there yet, but you are welcome to test on local -or custom repositories, or package pinnings. The reverse translation (2.0 to -1.2) is planned, to keep supporting 1.2 installations after that date. - -The documentation for the new version is available at -https://opam.ocaml.org/doc/2.0/. This is still work in progress, so please do ask -if anything is unclear. - -## Interface changes - -Commands `opam switch` and `opam list` have been rehauled for more consistency -and flexibility: the former won't implicitly create new switches unless called -with the `create` subcommand, and `opam list` now allows to combine filters and -finely specify the output format. They may not be fully backwards compatible, so -please check your scripts. - -Most other commands have also seen fixes or improvements. For example, opam -doesn't forget about your set of installed packages on the first error, and the -new `opam install --restore` can be used to reinstall your selection after a -failed upgrade. - -## Repository changes - -While users of opam 1.2 should feel at home with the changes, the 2.0 repository -and package formats are not compatible. Indeed, the move of the compilers to -standard packages implies some conversions, and updates to the relationships -between packages and their compiler. For example, package constraints like - - available: [ ocaml-version >= "4.02" ] - -are now written as normal package dependencies: - - depends: [ "ocaml" {>= "4.02"} ] - -To make the transition easier, -- upgrade of a custom repository is simply a matter of running `opam-admin - upgrade-format` at its root; -- the official repository at `opam.ocaml.org` already has a 2.0 mirror, to which - you will be automatically redirected; -- packages definition are automatically converted when you pin a package. - -Note that the `ocaml` package on the official repository is actually a wrapper -that depends on one of `ocaml-base-compiler`, `ocaml-system` or -`ocaml-variants`, which contain the different flavours of the actual compiler. -It is expected that it may only get picked up when requested by package -dependencies. - -## Package format changes - -The opam package definition format is very similar to before, but there are -quite a few extensions and some changes: - -- it is now mandatory to separate the `build:` and `install:` steps (this allows - tracking of installed files, better error recovery, and some optional security - features); -- the url and description can now optionally be included in the `opam` file - using the section `url {}` and fields `synopsis:` and `description:`; -- it is now possible to have dependencies toggled by globally-defined opam - variables (_e.g._ for a dependency needed on some OS only), or even rely on - the package information (_e.g._ have a dependency at the same version); -- the new `setenv:` field allows packages to export updates to environment - variables; -- custom fields `x-foo:` can be used for extensions and external tools; -- allow `"""` delimiters around unescaped strings -- `&` is now parsed with higher priority than `|` -- field `ocaml-version:` can no longer be used -- the `remove:` field should not be used anymore for simple cases (just removing - files) - -## Let's go then -- how to try it ? - -First, be aware that you'll be prompted to update your `~/.opam` to 2.0 format -before anything else, so if you value it, make a backup. Or just export -`OPAMROOT` to test the alpha on a temporary opam root. - -Packages for opam 2.0 are already in the opam repository, so if you have a -working opam installation of opam (at least 1.2.1), you can bootstrap as easily -as: - - opam install opam-devel - -This doesn't install the new opam to your PATH within the current opam root for -obvious reasons, so you can manually install it as e.g. "opam2" using: - - sudo cp $(opam config var "opam-devel:lib")/opam /usr/local/bin/opam2 - -You can otherwise install as usual: -- Using pre-built binaries (available for OSX and Linux x86, x86_64, armhf) and - our install script: - - wget https://raw.github.com/ocaml/opam/2.0-alpha4-devel/shell/opam_installer.sh -O - | sh -s /usr/local/bin - - Equivalently, - [pick your version](https://github.com/ocaml/opam/releases/2.0-alpha4) and - download it to your PATH; - -- Building from our inclusive source tarball: - [download here](https://github.com/ocaml/opam/releases/download/2.0-alpha4/opam-full-2.0-alpha4.tar.gz) - and build using `./configure && make lib-ext && make && make install` if you - have OCaml >= 4.01 already available, `make cold && make install` otherwise; - -- Or from [source](https://github.com/ocaml/opam/tree/2.0-alpha4), following the - included instructions from the README. Some files have been moved around, so - if your build fails after you updated an existing git clone, try to clean it - up (`git clean -fdx`). diff --git a/data/changelog/opam/2017-02-09-opam-2-0-beta.md b/data/changelog/opam/2017-02-09-opam-2-0-beta.md deleted file mode 100644 index 319e17e414..0000000000 --- a/data/changelog/opam/2017-02-09-opam-2-0-beta.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: "opam 2.0 Beta is out!" -authors: [ "Louis Gesbert" ] -description: "Release announcement for opam 2.0.0~beta" -tags: [opam, platform] ---- - -> UPDATE (2017-02-14): A beta2 is online, which fixes issues and performance of -> the `opam build` command. Get the new -> [binaries](https://github.com/ocaml/opam/releases/tag/2.0.0-beta2), or -> recompile the [opam-devel](https://opam.ocaml.org/packages/opam-devel/) package -> and replace the previous binary. - -We are pleased to announce that the beta release of opam 2.0 is now live! You -can try it already, bootstrapping from a working 1.2 opam installation, with: - -``` -opam update; opam install opam-devel -``` - -With about a thousand patches since the last stable release, we took the time to -gather feedback after [our last announcement](../opam-2-0-preview) and -implemented a couple of additional, most-wanted features: - -- An `opam build` command that, from the root of a source tree containing one - or more package definitions, can automatically handle initialisation and - building of the sources in a local switch. -- Support for - [repository signing](https://github.com/hannesm/conex-paper/raw/master/paper.pdf) - through the external [Conex](https://github.com/hannesm/conex) tool, being - developed in parallel. - -There are many more features, like the new `opam clean` and `opam admin` -commands, a new archive caching system, etc., but we'll let you check the full -[changelog](https://github.com/ocaml/opam/blob/2.0.0-beta/CHANGES). - -We also improved still on the -[already announced features](../opam-2-0-preview/#Afewhighlights), including -compilers as packages, local switches, per-switch repository configuration, -package file tracking, etc. - -The updated documentation is at https://opam.ocaml.org/doc/2.0/. If you are -developing in opam-related tools, you may also want to browse the -[new APIs](https://opam.ocaml.org/doc/2.0/api/index.html). - - -## Try it out - -Please try out the beta, and report any issues or missing features. You can: - -- Build it from source in opam, as shown above (`opam install opam-devel`) -- Use the [pre-built binaries](https://github.com/ocaml/opam/releases/tag/2.0.0-beta). -- Building from the source tarball: - [download here](https://github.com/ocaml/opam/releases/download/2.0.0-beta/opam-full-2.0.0-beta.tar.gz) - and build using `./configure && make lib-ext && make` if you have OCaml >= - 4.01 already available; `make cold` otherwise -- Or directly from the - [git tree](https://github.com/ocaml/opam/tree/2.0.0-beta), following the - instructions included in the README. Some files have been moved around, so if - your build fails after you updated an existing git clone, try to clean it up - (`git clean -dx`). - -Some users have been using the alpha for the past months without problems, but -you may want to keep your opam 1.2 installation intact until the release is out. -An easy way to do this is with an alias: - -``` -alias opam2="OPAMROOT=~/.opam2 path/to/opam-2-binary" -``` - - -## Changes to be aware of - -### Command-line interface - -- `opam switch create` is now needed to create new switches, and `opam switch` - is now much more expressive -- `opam list` is also much more expressive, but be aware that the output may - have changed if you used it in scripts -- new commands: - - `opam build`: setup and build a local source tree - - `opam clean`: various cleanup operations (wiping caches, etc.) - - `opam admin`: manage software repositories, including upgrading them to - opam 2.0 format (replaces the `opam-admin` tool) - - `opam env`, `opam exec`, `opam var`: shortcuts for the `opam config` subcommands -- `opam repository add` will now setup the new repository for the current switch - only, unless you specify `--all` -- Some flags, like `--test`, now apply to the packages listed on the - command-line only. For example, `opam install lwt --test` will build and - install lwt and all its dependencies, but only build/run the tests of the - `lwt` package. Test-dependencies of its dependencies are also ignored -- The new `opam install --soft-request` is useful for batch runs, it will - maximise the installed packages among the requested ones, but won't fail if - all can't be installed - -As before, opam is self-documenting, so be sure to check `opam COMMAND --help` -first when in doubt. The bash completion scripts have also been thoroughly -improved, and may help navigating the new options. - - -### Metadata - -There are both a few changes (extensions, mostly) to the package description -format, and more drastic changes to the repository format, mainly related to -translating the old compiler definitions into packages. - -- opam will automatically update, internally, definitions of pinned packages as - well as repositories in the 1.2 format -- however, it is faster to use repositories in the 2.0 format directly. To that - end, please use the `opam admin upgrade` command on your repositories. The - `--mirror` option will create a 2.0 mirror and put in place proper - redirections, allowing your original repository to retain the old format - -The official opam repository at https://opam.ocaml.org remains in 1.2 format for -now, but has a live-updated 2.0 mirror to which you should be automatically -redirected. It cannot yet accept package definitions in 2.0 format. - - -#### Package format - -- Any `available:` constraints based on the OCaml compiler version should be - rewritten into dependencies to the `ocaml` package -- Separate `build:` and `install:` instructions are now required -- It is now preferred to include the old `url` and `descr` files (containing the - archive URL and package description) in the `opam` file itself: (see the new - [`synopsis:`](https://opam.ocaml.org/doc/2.0/Manual.html#opamfield-synopsis) - and - [`description:`](https://opam.ocaml.org/doc/2.0/Manual.html#opamfield-description) - fields, and the - [url {}](https://opam.ocaml.org/doc/2.0/Manual.html#opamsection-url) file - section) -- Building tests and documentation should now be part of the main `build:` - instructions, using the `{test}` and `{doc}` filters. The `build-test:` and - `build-doc:` fields are still supported. -- It is now possible to use opam variables within dependencies, for example - `depends: [ "foo" {= version} ]`, for a dependency to package `foo` at the - same version as the package being defined, or `depends: - [ "bar" {os = "linux"} ]` for a dependency that only applies on Linux. -- The new `conflict-class:` field allows mutual conflicts among a set of - packages to be declared. Useful, for example, when there are many concurrent, - incompatible implementations. -- The `ocaml-version:` field has been deprecated for a long time and is no - longer accepted. This should now be a dependency on the `ocaml` package -- Three types of checksums are now accepted: you should use `md5=`, - `sha256=` or `sha512=`. We'll be gradually deprecating - md5 in favour of the more secure algorithms; multiple checksums are allowed -- Patches supplied in the `patches:` field must apply with `patch -p1` -- The new `setenv:` field allows packages to export updates to environment - variables; -- Custom fields `x-foo:` can be used for extensions and external tools -- `"""` delimiters allow unescaped strings -- `&` has now the customary higher precedence than `|` in formulas -- Installed files are now automatically tracked meaning that the `remove:` - field is usually no longer required. - -The full, up-to-date specification of the format can be browsed in the -[manual](https://opam.ocaml.org/doc/2.0/Manual.html#opam). - -#### Repository format - -In the official, default repository, and also when migrating repositories from -older format versions, there are: - -- A virtual `ocaml` package, that depends on any implementation of the OCaml - compiler. This is what packages should depend on, and the version is the - corresponding base OCaml version (e.g. `4.04.0` for the `4.04.0+fp` compiler). - It also defines various configuration variables, see `opam config list ocaml`. -- Three mutually-exclusive packages providing actual implementations of the - OCaml toolchain: - - `ocaml-base-compiler` is the official releases - - `ocaml-variants.+` contains all the other - variants - - `ocaml-system-compiler` maps to a compiler installed on the system - outside of opam - -The layout is otherwise the same, apart from: -- The `compilers/` directory is ignored -- A `repo` file should be present, containing at least the line `opam-version: "2.0"` -- The indexes for serving over HTTP have been simplified, and `urls.txt` is no - longer needed. See `opam admin index --help` -- The `archives/` directory is no longer used. The cache now uses a different - format and is configured through the `repo` file, defaulting to `cache/` on - the same server. See `opam admin cache --help` - -## Feedback - -Thanks for trying out the beta! Please let us have feedback, preferably to the -[opam tracker](https://github.com/ocaml/opam/issues); other options include the -[opam-devel](mailto:opam-devel@lists.ocaml.org) list and #opam IRC channel on -Freenode. diff --git a/data/changelog/opam/2017-11-27-opam-2-0-beta5.md b/data/changelog/opam/2017-11-27-opam-2-0-beta5.md deleted file mode 100644 index f9b119be56..0000000000 --- a/data/changelog/opam/2017-11-27-opam-2-0-beta5.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: "opam 2.0 Beta5 is out!" -authors: [ "Louis Gesbert" ] -description: "Release announcement for opam 2.0.0~beta5" -tags: [opam, platform] ---- - -After a few more months brewing, we are pleased to announce a new beta release -of opam. With this new milestone, opam is reaching feature-freeze, with an -expected 2.0.0 by the beginning of next year. - -This version brings many new features, stability fixes, and big improvements to -the local development workflows. - -## What's new - -The features presented in past announcements: -[local switches](https://opam.ocaml.org/blog/opam-local-switches/), -[in-source package definition handling](https://opam.ocaml.org/blog/opam-install-dir/), -[extended dependencies](https://opam.ocaml.org/blog/opam-extended-dependencies/) -are of course all present. But now, all the glue to make them interact nicely -together is here to provide new smooth workflows. For example, the following -command, if run from the source tree of a given project, creates a local switch -where it will restore a precise installation, including explicit versions of all -packages and pinnings: - -``` -opam switch create ./ --locked -``` - -this leverages the presence of `opam.locked` or `.opam.locked` files, -which are valid package definitions that contain additional details of the build -environment, and can be generated with the -[`opam-lock` plugin](https://github.com/AltGr/opam-lock) (the `lock` command may -be merged into opam once finalised). - -But this new beta also provides a large amount of quality of life improvements, -and other features. A big one, for example, is the integration of a built-in -solver (derived from [`mccs`](http://www.i3s.unice.fr/~cpjm/misc/mccs.html) and -[`glpk`](https://www.gnu.org/software/glpk/)). This means that the `opam` binary -works out-of-the box, without requiring the external -[`aspcud`](https://web.archive.org/web/20171023113455/http://www.cs.uni-potsdam.de/wv/aspcud/) solver, and on all -platforms. It is also faster. - -Another big change is that detection of architecture and OS details is now done -in opam, and can be used to select the external dependencies with the new format -of the [`depexts:`](https://opam.ocaml.org/doc/2.0/Manual.html#opamfield-depexts) -field, but also to affect dependencies or build flags. - -There is much more to it. Please see the -[changelog](https://github.com/ocaml/opam/blob/2.0.0-beta5/CHANGES), and the -[updated manual](https://opam.ocaml.org/doc/2.0/Manual.html). - -## How to try it out - -Our warm thanks for trying the new beta and -[reporting](https://github.com/ocaml/opam/issues) any issues you may hit. - - -1. The easiest is to use our pre-compiled binaries. - [This script](https://github.com/ocaml/opam/blob/master/shell/opam_installer.sh) - will also make backups if you migrate from 1.x, and has an option to revert - back: - - ``` - sh <(curl -sL https://opam.ocaml.org/install.sh) - ``` - - This uses the binaries from https://github.com/ocaml/opam/releases/tag/2.0.0-beta5 - -2. Another option is to compile from source, using an existing opam - installation. Simply run: - - ``` - opam update; opam install opam-devel - ``` - - and follow the instructions (you will need to copy the compiled binary to - your PATH). - -3. Compiling by hand from the - [inclusive source archive](https://github.com/ocaml/opam/releases/download/2.0.0-beta5/opam-full-2.0.0-beta5.tar.gz), - or from the [git repo](https://github.com/ocaml/opam/tree/2.0.0-beta5). Use - `./configure && make lib-ext && make` if you have OCaml >= 4.02.3 already - available; `make cold` otherwise. - - If the build fails after updating a git repo from a previous version, try - `git clean -fdx src/` to remove any stale artefacts. - -Note that the repository format is different from that of opam 1.2. Opam 2 will -be automatically redirected from the -[opam-repository](https://github.com/ocaml/opam-repository) to an automatically -rewritten 2.0 mirror, and is otherwise able to do the conversion on the fly -(both for package definitions when pinning, and for whole repositories). You may -not yet contribute packages in 2.0 format to opam-repository, though. - -## What we need tested - -We are interested in all opinions and reports, but here are a few areas where -your feedback would be specially useful to us: - -- Use 2.0 day-to-day, in particular check any packages you may be maintaining. - We would like to ensure there are no regressions due to the rewrite from 1.2 - to 2.0. -- Check the quality of the solutions provided by the solver (or conflicts, when - applicable). -- Test the different pinning mechanisms (rsync, git, hg, darcs) with your - project version control systems. See the `--working-dir` option. -- Experiment with local switches for your project (and/or `opam install DIR`). - Give us feedback on the workflow. Use `opam lock` and share development - environments. -- If you have any custom repositories, please try the conversion to 2.0 format - with `opam admin upgrade --mirror` on them, and use the generated mirror. -- Start porting your CI systems for larger projects to use opam 2, and give us - feedback on any improvements you need for automated scripting (e.g. the - `--json` output). diff --git a/data/changelog/opam/2018-02-02-opam-2-0-0-rc.md b/data/changelog/opam/2018-02-02-opam-2-0-0-rc.md deleted file mode 100644 index 63d8afc560..0000000000 --- a/data/changelog/opam/2018-02-02-opam-2-0-0-rc.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "opam 2.0.0 Release Candidate 1 is out!" -authors: [ "Louis Gesbert" ] -description: "Release announcement for OPAM 2.0.0~rc1" -tags: [opam, platform] ---- - -We are pleased to announce a first release candidate for the long-awaited opam 2.0.0. - -A lot of polishing has been done since the [last beta](https://opam.ocaml.org/blog/opam-2-0-beta5/), including tweaks to the built-in solver, allowing in-source package definitions to be gathered in an `opam/` directory, and much more. - -With all of the 2.0.0 features getting pretty solid, we are now focusing on bringing all the guides up-to-date[¹](#foot-1), updating the tools and infrastructure, making sure there are no usability issues with the new workflows, and being future-proof so that further updates break as little as possible. - -You are invited to read the [beta5 announcement](https://opam.ocaml.org/blog/opam-2-0-beta5/) for details on the 2.0.0 features. Installation instructions haven't changed: - -1. From binaries: run - - ``` - sh <(curl -sL https://opam.ocaml.org/install.sh) - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.0.0-rc) to your PATH. - -2. From source, using opam: - - ``` - opam update; opam install opam-devel - ``` - - (then copy the opam binary to your PATH as explained) - -3. From source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.0.0-rc#opam---a-package-manager-for-ocaml). - -Thanks a lot for testing out the RC and [reporting](https://github.com/ocaml/opam/issues) any issues you may find. See [what we need tested](https://opam.ocaml.org/blog/opam-2-0-beta5/#What-we-need-tested) for more detail. - ---- - -¹ You can at the moment rely on the [manpages](https://opam.ocaml.org/doc/2.0/man/opam.html), the [Manual](https://opam.ocaml.org/doc/2.0/Manual.html), and of course the [API](https://opam.ocaml.org/doc/2.0/api/), but other pages might be outdated. diff --git a/data/changelog/opam/2018-05-22-opam-2-0-0-rc2.md b/data/changelog/opam/2018-05-22-opam-2-0-0-rc2.md deleted file mode 100644 index 228886f523..0000000000 --- a/data/changelog/opam/2018-05-22-opam-2-0-0-rc2.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "opam 2.0.0 Release Candidate 2 is out!" -authors: [ "Louis Gesbert" ] -description: "Release announcement for OPAM 2.0.0~rc2" -tags: [opam, platform] ---- - -We are pleased to announce the release of a second release candidate for opam 2.0.0. - -This new version brings us very close to a final 2.0.0 release, and in addition to many fixes, features big performance enhancements over the RC1. - -Among the new features, we have squeezed in full sandboxing of package commands for both Linux and macOS, to protect our users from any [misbehaving scripts](https://opam.ocaml.org/blog/camlp5-system/). - -> NOTE: if upgrading manually from 2.0.0~rc, you need to run -> `opam init --reinit -ni` to enable sandboxing. - -The new release candidate also offers the possibility to setup a hook in your shell, so that you won't need to run `eval $(opam env)` anymore. This is specially useful in combination with local switches, because with it enabled, you are guaranteed that running `make` from a project directory containing a local switch will use it. - -The documentation has also been updated, and a preview of the opam 2 webpages can be browsed at https://opam.ocaml.org/2.0-preview/ (please report issues [here](https://github.com/ocaml/opam2web/issues)). This provides the list of packages available for opam 2 (the `2.0` branch of [opam-repository](https://github.com/ocaml/opam-repository)), including the compiler packages. - -Installation instructions: - -1. From binaries: run - - ``` - sh <(curl -sL https://opam.ocaml.org/install.sh) - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.0.0-rc2) to your PATH. In this case, don't forget to run `opam init --reinit -ni` to enable sandboxing if you had version 2.0.0~rc manually installed. - -2. From source, using opam: - - ``` - opam update; opam install opam-devel - ``` - - (then copy the opam binary to your PATH as explained, and don't forget to run `opam init --reinit -ni` to enable sandboxing if you had version 2.0.0~rc manually installed) - -3. From source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.0.0-rc2#compiling-this-repo). - -Thanks a lot for testing out this new RC and [reporting](https://github.com/ocaml/opam/issues) any issues you may find. - - -> NOTE: this article is cross-posted on [opam.ocaml.org](https://opam.ocaml.org/blog/) and [ocamlpro.com](http://www.ocamlpro.com/category/blog/). Please head to the latter for the comments! diff --git a/data/changelog/opam/2018-06-22-opam-2-0-0-rc3.md b/data/changelog/opam/2018-06-22-opam-2-0-0-rc3.md deleted file mode 100644 index 7e78562d5f..0000000000 --- a/data/changelog/opam/2018-06-22-opam-2-0-0-rc3.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "opam 2.0.0 Release Candidate 3 is out!" -authors: [ "Raja Boujbel", "Louis Gesbert"] -description: "Release announcement for OPAM 2.0.0~rc3" -tags: [opam, platform] ---- - -We are pleased to announce the release of a third release candidate for opam 2.0.0. This one is expected to be the last before 2.0.0 comes out. - -Changes since the [2.0.0~rc2](../opam-2-0-0-rc2) are, as expected, mostly fixes. We deemed it useful, however, to bring in the following: - -- a new command `opam switch link` that allows to select a switch to be used in a given directory (particularly convenient if you use the shell hook for automatic opam environment update) -- a new option `opam install --assume-built`, that allows to install a package using its normal opam procedure, but for a source repository that has been built by hand. This fills a gap that remained in the local development workflows. - -The preview of the opam 2 webpages can be browsed at https://opam.ocaml.org/2.0-preview/ (please report issues [here](https://github.com/ocaml/opam2web/issues)). - -Installation instructions (unchanged): - -1. From binaries: run - - ``` - sh <(curl -sL https://opam.ocaml.org/install.sh) - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.0.0-rc3) to your PATH. In this case, don't forget to run `opam init --reinit -ni` to enable sandboxing if you had version 2.0.0~rc manually installed. - -2. From source, using opam: - - ``` - opam update; opam install opam-devel - ``` - - (then copy the opam binary to your PATH as explained, and don't forget to run `opam init --reinit -ni` to enable sandboxing if you had version 2.0.0~rc manually installed) - -3. From source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.0.0-rc3#compiling-this-repo). - -Thanks a lot for testing out this new RC and [reporting](https://github.com/ocaml/opam/issues) any issues you may find. diff --git a/data/changelog/opam/2018-07-26-opam-2-0-0-rc4.md b/data/changelog/opam/2018-07-26-opam-2-0-0-rc4.md deleted file mode 100644 index 2982740add..0000000000 --- a/data/changelog/opam/2018-07-26-opam-2-0-0-rc4.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "opam 2.0.0 RC4-final is out!" -authors: [ "Raja Boujbel", "Louis Gesbert"] -description: "Release announcement for OPAM 2.0.0~rc4" -tags: [opam, platform] ---- - -We are happy to announce the [opam 2.0.0 final release candidate](https://github.com/ocaml/opam/releases/tag/2.0.0-rc4)! 🍾 - -This release features a few bugfixes over [Release Candidate 3](../opam-2-0-0-rc3). **It will be promoted to 2.0.0 proper within a few weeks, when the [official repository](https://github.com/ocaml/opam-repository) format switches from 1.2.0 to 2.0.0.** After that date, updates to the 1.2.0 repository may become limited, as new features are getting used in packages. - -It is safe to update as soon as you see fit, since opam 2.0.0 supports the older formats. See the [Upgrade Guide](https://opam.ocaml.org/doc/Upgrade_guide.html) for details about the new features and changes. If you are a package maintainer, you should keep publishing as before for now: the [roadmap](https://opam.ocaml.org/blog/opam-2-0-0-repo-upgrade-roadmap) for the repository upgrade will be detailed shortly. - -The opam.ocaml.org pages have also been refreshed a bit, and the new version showing the 2.0.0 branch of the repository is already online. Report any issues [here](https://github.com/ocaml/opam2web/issues). - - ---- - -Installation instructions: - -1. From binaries: run - - ``` - sh <(curl -sL https://opam.ocaml.org/install.sh) - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.0.0-rc4) to your PATH. In this case, don't forget to run `opam init --reinit -ni` to enable sandboxing if you had version 2.0.0~rc manually installed. - -2. From source, using opam: - - ``` - opam update; opam install opam-devel - ``` - - (then copy the opam binary to your PATH as explained, and don't forget to run `opam init --reinit -ni` to enable sandboxing if you had version 2.0.0~rc manually installed) - -3. From source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.0.0-rc4#compiling-this-repo). - -We hope you enjoy this new version, and remain open to [bug reports](https://github.com/ocaml/opam/issues) and [suggestions](https://github.com/ocaml/opam/issues). - -> NOTE: this article is cross-posted on [opam.ocaml.org](https://opam.ocaml.org/blog/) and [ocamlpro.com](http://www.ocamlpro.com/category/blog/). Please head to the latter for the comments! diff --git a/data/changelog/opam/2020-04-21-opam-2-1-0-alpha.md b/data/changelog/opam/2020-04-21-opam-2-1-0-alpha.md deleted file mode 100644 index cd5d1841c5..0000000000 --- a/data/changelog/opam/2020-04-21-opam-2-1-0-alpha.md +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: "opam 2.1.0 alpha is here!" -authors: [ "Raja Boujbel", "Louis Gesbert"] -description: "Release announcement for opam 2.1.0~alpha" -tags: [opam, platform] ---- - -We are happy to announce a alpha for opam 2.1.0, one year and a half in the -making after the release of 2.0.0. - -Many new features made it in (see the [complete -changelog](https://github.com/ocaml/opam/blob/2.1.0-alpha/CHANGES) or [release -note](https://github.com/ocaml/opam/releases/tag/2.1.0-alpha) for the details), -but here are a few highlights of this release. - - -# Release highlights - -The two following features have been around for a while as plugins and are now -completely integrated in the core of opam. No extra installs needed anymore, and -a more smooth experience. - - -### Seamless integration of System dependencies handling (a.k.a. "depexts") - -A number of opam packages depend on tools or libraries installed on the system, -which are out of the scope of opam itself. Previous versions of opam added a -[specification format](https://opam.ocaml.org/doc/Manual.html#opamfield-depexts), -and opam 2.0 already handled checking the OS and extracting the required system -package names. - -However, the workflow generally involved letting opam fail once, then installing -the dependencies and retrying, or explicitely using the -[opam-depext plugin](https://github.com/ocaml/opam-depext), which was invaluable -for CI but still incurred extra steps. - -With opam 2.1.0, _depexts_ are seamlessly integrated, and you basically won't -have to worry about them ahead of time: - -- Before applying its course of actions, opam 2.1.0 checks that external - dependencies are present, and will prompt you to install them. You are free to - let it do it using `sudo`, or just run the provided commands yourself. -- It is resilient to _depexts_ getting removed or out of sync. -- Opam 2.1.0 detects packages that depend on stuff that is not available on your - OS version, and automatically avoids them. - -This is all fully configurable, and can be bypassed without tricky commands when -you need it (_e.g._ when you compiled a dependency yourself). - - -### Dependency locking - -To share a project for development, it is often necessary to be able to -reproduce the exact same environment and dependencies setting — as opposed to -allowing a range of versions as opam encourages you to do for releases. - -For some reason, most other package managers call this feature "lock files". -Opam can handle those in the form of `[foo.]opam.locked` files, and the -`--locked` option. - -With 2.1.0, you no longer need a plugin to generate these files: just running -`opam lock` will create them for existing `opam` files, enforcing the exact -version of all dependencies (including locally pinned packages). - -If you check-in these files, new users would just have run -`opam switch create . --locked` on a fresh clone to get a local switch ready to -build the project. - - -### Pinning sub-directories - -This one is completely new: fans of the _Monorepo_ rejoice, opam is now able to -handle projects in subtrees of a repository. - -- Using `opam pin PROJECT_ROOT --subpath SUB_PROJECT`, opam will look for - `PROJECT_ROOT/SUB_PROJECT/foo.opam`. This will behave as a pinning to - `PROJECT_ROOT/SUB_PROJECT`, except that the version-control handling is done - in `PROJECT_ROOT`. -- Use `opam pin PROJECT_ROOT --recursive` to automatically lookup all sub-trees - with opam files and pin them. - - -### Opam switches are now defined by invariants - -Previous versions of opam defined switches based on _base packages_, which -typically included a compiler, and were immutable. Opam 2.1.0 instead defines -them in terms of an _invariant_, which is a generic dependency formula. - -This removes a lot of the rigidity `opam switch` commands had, with little -changes on the existing commands. For example, `opam upgrade ocaml` commands are -now possible; you could also define the invariant as `ocaml-system` and have -its version change along with the version of the OCaml compiler installed -system-wide. - - -### Configuring opam from the command-line - -The new `opam option` command allows to configure several options, -without requiring manual edition of the configuration files. - -For example: -- `opam option jobs=6 --global` will set the number of parallel build - jobs opam is allowed to run (along with the associated `jobs` variable) -- `opam option depext-run-commands=false` disables the use of `sudo` for - handling system dependencies; it will be replaced by a prompt to run the - installation commands. - -The command `opam var` is extended with the same format, acting on switch and -global variables. - -# Try it! - -In case you plan a possible rollback, you may want to first backup your -`~/.opam` directory. - -The upgrade instructions are unchanged: - -1. Either from binaries: run - - ``` - bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.1.0~alpha" - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.1.0-alpha) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.1.0-alpha#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -This is still a alpha, so a few glitches or regressions are to be expected. -Please report them to [the bug-tracker](https://github.com/ocaml/opam/issues). -Thanks for trying it out, and hoping you enjoy! - - -> NOTE: this article is cross-posted on -[opam.ocaml.org](https://opam.ocaml.org/blog/) and -[ocamlpro.com](http://www.ocamlpro.com/category/blog/). Please head to the -latter for the comments! diff --git a/data/changelog/opam/2020-10-19-opam-2-1-0-beta2.md b/data/changelog/opam/2020-10-19-opam-2-1-0-beta2.md deleted file mode 100644 index 8f959132b7..0000000000 --- a/data/changelog/opam/2020-10-19-opam-2-1-0-beta2.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: "opam 2.1.0~beta4 released" -authors: [ "David Allsopp" ] -description: "Release announcement for opam 2.1.0~beta2" -tags: [opam, platform] -changelog: | - * Reduced startup times, in particular for `opam exec` [#4341 @altgr] - * Fixed the sandboxing check on fresh inits [#4342 @altgr] - * Fixed cases where `--with-version` was not respected by `opam pin` [#4346 @altgr] - * Upgraded the bootstrap OCaml compiler from 4.09.1 to 4.11.1 [#4242 @avsm @dra27 @MisterDA @rjbou] ---- diff --git a/data/changelog/opam/2021-02-08-opam-2-1-0-beta4.md b/data/changelog/opam/2021-02-08-opam-2-1-0-beta4.md deleted file mode 100644 index c92c35cf0d..0000000000 --- a/data/changelog/opam/2021-02-08-opam-2-1-0-beta4.md +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: "opam 2.1.0~beta4 released" -authors: [ "David Allsopp" ] -description: "Release announcement for opam 2.1.0~beta4" -tags: [opam, platform] -changelog: | - * (*) Implemented CLI version compatibility layer [#4385 @rjbou] - * (*) Return code 31 (`Sync_error`) instead of code 40 - (`Package_operation_error`) when all failures happend during fetching - [#4416 @rjbou - fix #4214] - * (+) Add `--download-only` flag [#4071 @Armael @rjbou - fix #4036] - * (+) Provide `opam update --depexts` to request an update of the system package manager databases [#4379 @AltGr - fix #4355] - * Set OPAMCLI=2.0 during package action commands [#4492 @kit-ty-kate] - * Fix sandbox check on first `opam init` [#4370 @rjbou - fix #4368] - * Print shell-appropriate eval command on `opam init` [#4427 @freevoid] - * Fix `init` script check in csh [#4482 @gahr] - * The `stdout` of `pre-` and `post-session` hooks is now propagated to the user [#4382 @AltGr - fix #4359] - * `post-install` hooks are now allowed to modify or remove installed files [#4388 @lefessan] - * Add support for switch-specific pre/post sessions hooks [#4476 @rjbou - fix #4472] - * Ensure we don't advertise upgrades to hidden versions [#4477 @AltGr - fix #4432] - * Fix `opam remove --autoremove ` to not autoremove unrelated packages [#4369 @AltGr - fix #4250 #4332] - * Fix cases where `opam remove -a` could trigger conflicts in the presence of orphan packages [#4369 @AltGr - fix #4250 #4332] - * Fix `--update-invariant` when removing or changing package name [#4360 @AltGr - fix #4353] - * Fix updates of the invariant with `--update-invariant` [#4431 @AltGr] - * Fix cleanup of build dirs for version pinned packages [#4436 @rjbou - fix #4255] - * Fix `opamfile` format upgrade on pinning [#4366 @rjbou - fix #4365] - * Fix `pin --show` actually pinning [#4367 @rjbou - fix #4348] - * When several pins are needed, do their fetching in parallel [#4399 @rjbou - fix #4315] - * Don't cleanup VCS pin source directories [#4399 @rjbou] - * Fix `--working-dir` with local switches [#4433 @rjbou] - * Add package variable `opamfile-loc`, containing the location of installed package opam file [#4402 @rjbou] - * Fix `arch` detection when using 32bit mode on ARM64 [#4462 @kit-ty-kate] - * Fix `arch` detection of i486 [#4462 @kit-ty-kate] - * Skip loading the switch state for variable lookup when possible [#4428 @rjbou] - * Fix package variables display when no config file is found [#4428 @rjbou] - * Fix `opam option depext-bypass-=["XXX"]` [#4428 @rjbou] - * Lint: add a check that strings in filtered package formula are Booleans or variables [#443 @rjbou - fix #4439] - * Fix handling of filename-encoded pkgname in opam files [#4401 @AltGr - fix ocaml-opam/opam-publish#107] - * Don't recompile when modifying the package flags [#4477 @AltGr] - * Add depext support for NetBSD and DragonFlyBSD [#4396 @kit-ty-kate] - * Fix depexts on OpenBSD, FreeBSD, and Gentoo: Allow short names and full name paths for ports-based systems [#4396 @kit-ty-kate] - * Handle the case where `os-family=ubuntu` as `os-family=debian` [#4441 @alan-j-hu] - * Update opam's `opam` files to 2.0 [#4371 @AltGr] - * Makefile: Add rule `custom-libinstall` for `opam-custom-install` use [#4401 @AltGr] - * Use the archive caches when running `opam admin cache` [#4384 @AltGr - fix #4352] - * Fix explosion of `opam admin check --cycles` on repositories with huge cliques [#4392 @AltGr] - * Much improved format-preserving printer [#4298 #4302 @rjbou - fix #3993] - * Fix missing conflict message when trying to remove required packages [#4362 @AltGr] - * Fix the Z3 backend for upgrades [#4393 @AltGr] - * Fix cases where opam would wrongly complain about action cycles [#4358 @AltGr - fix #4357] - * Fix permission denied fallback for `openssl` [#4449 @Blaisorblade - fix #4448] - * Add debug & verbose log for patch & `subst` applications [#4464 @rjbou - fix #4453] - * Be more robust w.r.t. new caches updates when `--read-only` is not used [#4467 @AltGr - fix #4354] - * Improved and extended tests [#4375 #4395 #4428 #4385 #4467 #4475 #4483 @emillon @rjbou @AltGr @freevoid @dra27] - * Switched to GitHub actions [#4463 @rjbou] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-1-0-beta4/7252)!_ - -On behalf of the opam team, it gives me great pleasure to announce the third beta release of opam 2.1. Don’t worry, you didn’t miss beta3 - we had an issue with a configure script that caused beta2 to report as beta3 in some instances, so we skipped to beta4 to avoid any further confusion! - -We encourage you to try out this new beta release: there are instructions for doing so in [our wiki](https://github.com/ocaml/opam/wiki/How-to-test-an-opam-feature). The instructions include taking a backup of your `~/.opam` root as part of the process, which can be restored in order to wind back. _Please note that local switches which are written to by opam 2.1 are upgraded and will need to be rebuilt if you go back to opam 2.0_. This can either be done by removing `_opam` and repeating whatever you use in your build process to create the switch, or you can use `opam switch export switch.export` to backup the switch to a file before installing new packages. Note that opam 2.1 _shouldn’t_ upgrade a local switch unless you upgrade the base packages (i.e. the compiler). - -## What’s new in opam 2.1? - -- Switch invariants -- Improved options configuration (see the new `option` and expanded `var` sub-commands) -- Integration of system dependencies (formerly the opam-depext plugin), increasing their reliability as it integrates the solving step -- Creation of lock files for reproducible installations (formerly the opam-lock plugin) -- CLI versioning, allowing cleaner deprecations for opam now and also improvements to semantics in future without breaking backwards-compatibility -- Performance improvements to opam-update, conflict messages, and many other areas -- New plugins: opam-compiler and opam-monorepo - -### Switch invariants - -In opam 2.0, when a switch is created the packages selected are put into the “base” of the switch. These packages are not normally considered for upgrade, in order to ease pressure on opam’s solver. This was a much bigger concern early on in opam 2.0’s development, but is less of a problem with the default mccs solver. - -However, it’s a problem for system compilers. opam would detect that your system compiler version had changed, but be unable to upgrade the ocaml-system package unless you went through a slightly convoluted process with `--unlock-base`. - -In opam 2.1, base packages have been replaced by switch invariants. The switch invariant is a package formula which must be satisfied on every upgrade and install. All existing switches’ base packages could just be expressed as `package1 & package2 & package3` etc. but opam 2.1 recognises many existing patterns and simplifies them, so in most cases the invariant will be `"ocaml-base-compiler" {= 4.11.1}`, etc. This means that `opam switch create my_switch ocaml-system` now creates a _switch invariant_ of `"ocaml-system"` rather than a specific version of the `ocaml-system` package. If your system OCaml package is updated, `opam upgrade` will seamlessly switch to the new package. - -This also allows you to have switches which automatically install new point releases of OCaml. For example: - -``` -opam switch create ocaml-4.11 --formula='"ocaml-base-compiler" {>= "4.11.0" & < "4.12.0~"}' --repos=old=git+https://github.com/ocaml/opam-repository#a11299d81591 -opam install utop - -``` - -Creates a switch with OCaml 4.11.0 (the `--repos=` was just to select a version of opam-repository from before 4.11.1 was released). Now issue: - -``` -opam repo set-url old git+https://github.com/ocaml/opam-repository -opam upgrade -``` - -and opam 2.1 will automatically offer to upgrade OCaml 4.11.1 along with a rebuild of the switch. There’s not yet a clean CLI for specifying the formula, but we intend to iterate further on this with future opam releases so that there is an easier way of saying “install OCaml 4.11.x”. - -### opam depext integration - -opam has long included the ability to install system dependencies automatically via the [depext plugin](https://github.com/ocaml-opam/opam-depext). This plugin has been promoted to a native feature of opam 2.1.0 onwards, giving the following benefits: - -- You no longer have to remember to run `opam depext`, opam always checks depexts (there are options to disable this or automate it for CI use). Installation of an opam package in a CI system is now as easy as `opam install .`, without having to do the dance of `opam pin add -n/depext/install`. Just one command now for the common case! -- The solver is only called once, which both saves time and also stabilises the behaviour of opam in cases where the solver result is not stable. It was possible to get one package solution for the `opam depext` stage and a different solution for the `opam install` stage, resulting in some depexts missing. -- opam now has full knowledge of depexts, which means that packages can be automatically selected based on whether a system package is already installed. For example, if you have *neither* MariaDB nor MySQL dev libraries installed, `opam install mysql` will offer to install `conf-mysql` and `mysql`, but if you have the MariaDB dev libraries installed, opam will offer to install `conf-mariadb` and `mysql`. - -### opam lock files and reproducibility - -When opam was first released, it had the mission of gathering together scattered OCaml source code to build a [community repository](https://github.com/ocaml/opam-repository). As time marches on, the size of the opam repository has grown tremendously, to over 3000 unique packages with over 18000 unique versions. opam looks at all these packages and is designed to solve for the best constraints for a given package, so that your project can keep up with releases of your dependencies. - -While this works well for libraries, we need a different strategy for projects that need to test and ship using a fixed set of dependencies. To satisfy this use-case, opam 2.0.0 shipped with support for _using_ `project.opam.locked` files. These are normal opam files but with exact versions of dependencies. The lock file can be used as simply as `opam install . --locked` to have a reproducible package installation. - -With opam 2.1.0, the creation of lock files is also now integrated into the client: -- `opam lock` will create a `.locked` file for your current switch and project, that you can check into the repository. -- `opam switch create . --locked` can be used by users to reproduce your dependencies in a fresh switch. - -This lets a project simultaneously keep up with the latest dependencies (without lock files) while providing a stricter set for projects that need it (with lock files). - -### CLI Versioning - -A new `--cli` switch was added to the first beta release, but it’s only now that it’s being widely used. opam is a complex enough system that sometimes bug fixes need to change the semantics of some commands. For example: - -- `opam show --file` needed to change behaviour -- The addition of new controls for setting global variables means that the `opam config` was becoming cluttered and some things want to move to `opam var` -- `opam switch install 4.11.1` still works in opam 2.0, but it’s really an OPAM 1.2.2 syntax. - -Changing the CLI is exceptionally painful since it can break scripts and tools which themselves need to drive `opam`. CLI versioning is our attempt to solve this. The feature is inspired by the `(lang dune ...)` stanza in `dune-project` files which has allowed the Dune project to rename variables and alter semantics without requiring every single package using Dune to upgrade their `dune` files on each release. - -Now you can specify which version of opam you expected the command to be run against. In day-to-day use of opam at the terminal, you wouldn’t specify it, and you’ll get the latest version of the CLI. For example: `opam var --global` is the same as `opam var --cli=2.1 --global`. However, if you issue `opam var --cli=2.0 --global`, you will told that `--global` was added in 2.1 and so is not available to you. You can see similar things with the renaming of `opam upgrade --unlock-base` to `opam upgrade --update-invariant`. - -The intention is that `--cli` should be used in scripts, user guides (e.g. blog posts), and in software which calls opam. The only decision you have to take is the _oldest_ version of opam which you need to support. If your script is using a new opam 2.1 feature (for example `opam switch create --formula=`) then you simply don’t support opam 2.0. If you need to support opam 2.0, then you can’t use `--formula` and should use `--packages` instead. opam 2.0 does not have the `--cli` option, so for opam 2.0 instead of `--cli=2.0` you should set the environment variable `OPAMCLI` to `2.0`. As with _all_ opam command line switches, `OPAMCLI` is simply the equivalent of `--cli` which opam 2.1 will pick-up but opam 2.0 will quietly ignore (and, as with other options, the command line takes precedence over the environment). - -Note that opam 2.1 sets `OPAMCLI=2.0` when building packages, so on the rare instances where you need to use the `opam` command in a _package_ `build:` command (or in your build system), you _must_ specify `--cli=2.1` if you’re using new features. - -There’s even more detail on this feature [in our wiki](https://github.com/ocaml/opam/wiki/Spec-for-opam-CLI-versioning). We’re still finalising some details on exactly how `opam` behaves when `--cli` is not given, but we’re hoping that this feature will make it much easier in future releases for opam to make required changes and improvements to the CLI without breaking existing set-ups and tools. - -## What’s new since the last beta? - -- opam now uses CLI versioning ([#4385](https://github.com/ocaml/opam/pull/4385)) -- opam now exits with code 31 if all failures were during fetch operations ([#4214](https://github.com/ocaml/opam/issues/4214)) -- `opam install` now has a `--download-only` flag ([#4036](https://github.com/ocaml/opam/issues/4036)), allowing opam’s caches to be primed -- `opam init` now advises the correct shell-specific command for `eval $(opam env)` ([#4427](https://github.com/ocaml/opam/pull/4427)) -- `post-install` hooks are now allowed to modify or remove installed files ([#4388](https://github.com/ocaml/opam/pull/4388)) -- New package variable `opamfile-loc` with the location of the installed package opam file ([#4402](https://github.com/ocaml/opam/pull/4402)) -- `opam update` now has `--depexts` flag ([#4355](https://github.com/ocaml/opam/issues/4355)), allowing the system package manager to update too -- depext support NetBSD and DragonFlyBSD added ([#4396](https://github.com/ocaml/opam/pull/4396)) -- The format-preserving opam file printer has been overhauled ([#3993](https://github.com/ocaml/opam/issues/3993), [#4298](https://github.com/ocaml/opam/pull/4298) and [#4302](https://github.com/ocaml/opam/pull/4302)) -- pins are now fetched in parallel ([#4315](https://github.com/ocaml/opam/issues/4315)) -- `os-family=ubuntu` is now treated as `os-family=debian` ([#4441](https://github.com/ocaml/opam/pull/4441)) -- `opam lint` now checks that strings in filtered package formulae are booleans or variables ([#4439](https://github.com/ocaml/opam/issues/4439)) - -and many other bug fixes as listed [on the release page](https://github.com/ocaml/opam/releases/tag/2.1.0-beta4). - -## New Plugins - -Several features that were formerly plugins have been integrated into opam 2.1.0. We have also developed some _new_ plugins that satisfy emerging workflows from the community and the core OCaml team. They are available for use with the opam 2.1 beta as well, and feedback on them should be directed to the respective GitHub trackers for those plugins. - -### opam compiler - -The [`opam compiler`](https://github.com/ocaml-opam/opam-compiler) plugin can be used to create switches from various sources such as the main opam repository, the ocaml-multicore fork, or a local development directory. It can use Git tag names, branch names, or PR numbers to specify what to install. - -Once installed, these are normal opam switches, and one can install packages in them. To iterate on a compiler feature and try opam packages at the same time, it supports two ways to reinstall the compiler: either a safe and slow technique that will reinstall all packages, or a quick way that will just overwrite the compiler in place. - -### opam monorepo - -The [`opam monorepo`](https://github.com/ocamllabs/opam-monorepo) plugin lets you assemble standalone dune workspaces with your projects and all of their opam dependencies, letting you build it all from scratch using only Dune and OCaml. This satisfies the “monorepo” workflow which is commonly requested by large projects that need all of their dependencies in one place. It is also being used by projects that need global cross-compilation for all aspects of a codebase (including C stubs in packages), such as the MirageOS unikernel framework. - -## Next Steps - -This is anticipated to be the final beta in the 2.1 series, and we will be moving to release candidate status after this. We could really use your help with testing this release in your infrastructure and projects and let us know if you run into any blockers. If you have feature requests, please also report them on [our issue tracker](https://github.com/ocaml/opam/issues) -- we will be planning the next release cycle once we ship opam 2.1.0 shortly. diff --git a/data/changelog/opam/2021-06-16-opam-2-1-0-rc.md b/data/changelog/opam/2021-06-16-opam-2-1-0-rc.md deleted file mode 100644 index 77d2bc55e8..0000000000 --- a/data/changelog/opam/2021-06-16-opam-2-1-0-rc.md +++ /dev/null @@ -1,203 +0,0 @@ ---- -title: "opam 2.1.0~rc2 released" -authors: [ "David Allsopp" ] -description: "Release announcement for opam 2.1.0~rv2" -tags: [opam, platform] -changelog: | - * (*) Environment variables initialised only at opam client launch, no more via - libraries [#4606 #4703 @rjbou] - * (*) Deprecated `build-doc`, `build-test`, `make` flags [#4581 @rjbou] - * (+) Add `--confirm-level` and `OPAMCONFIRMLEVEL` for automatic answering - [#4582 @rjbou - fix #4168; #4683 @dra27 - fix #4682; #4691 @rjbou - fix #4682] - * (+) Add `--no` [#4582 @rjbou] - * (+) Add a `--with-0install-solver` option to the configure script to enable - the 'builtin-0install' solver [#4646 @kit-ty-kate] - * Add default CLI mechanism: deprecated options are accepted (in the major - version) if no CLI is specified [#4575 @rjbou] - * Add `opam config` deprecated subcommands in the default CLI - [#4575 @rjbou - fix #4503] - * Add CLI versioning for opam environment variables [#4606 @rjbou] - * Add CLI versioning for enums of flags with predefined enums [#4606 @rjbou] - * Clearer messages about using `--cli` and OPAMCLI [#4655 @dra27] - * The options `--root` and `--switch` are now reflected in environment - variables when building packages so that calls to `opam` during build access - the correct root and switch [#4668 @LasseBlaauwbroek] - * Add CLI versioning for enums of flags with predefined enums [#4626 @rjbou] - * Preprocess `--confirm-level` for plugins calls/install [#4694 @rjbou] - * Ensure the symlink for a plugin is maintained on each invocation - [#4621 @dra27 - partially fixes #4619] - * Initialise environment variables for plugins call/install [#4582 @rjbou] - * Expect plugins to end in `.exe` on Windows [#4709 @dra27] - * Introduce a `default-invariant` config field, restore the 2.0 semantics for - `default-compiler` [#4607 @AltGr] - * Fix default invariant with no system compiler [#4644 @AltGr - fix #4640] - * Perform an hard upgrade on intermediate roots, i.e., root from `2.1~alpha/beta`, - and keep a light upgrade from `2.0` [#4638 @rjbou] - * Send the 'opam root layout update' message to `stderr` [#4692 @AltGr] - * If opam root is different from the binary, allow reading it and try to read - in best effort mode [#4638 @rjbou - fix #4636] - * Don't check opam system dependencies on reinit after a format upgrade - [#4638 @rjbou] - * Fix `sys-ocaml-cc`, `sys-ocaml-arch`, and `sys-ocaml-libc` when no system - compiler installed [#4706 @dra27] - * Fix `Not_found` (config file) in config report [#4570 @rjbou] - * Config report: Print variables of installed compilers and their (installed) - dependencies [#4570 @rjbou] - * Don't patch twice file [#4529 @rjbou] - * With `--deps-only`, set dependencies as root packages - [#4964 @rjbou - fix #4502] - * Keep global lock only if root format upgrade is performed - [#4612 @rjbou - fix #4597] - * Improve installation times by only tracking files listed in `.install` - instead of the whole switch prefix when there are no `install:` instructions - (and no preinstall commands) - [#4494 @kit-ty-kate @rjbou; #4667 @dra27 - fix #4422] - * Scrub opam* environment variables added since 2.0 from package builds to - prevent warnings when a package calls opam [#4663 @dra27 - fix #4660] - * Correct the message when more than one depext is missing [#4678 @dra27] - * Only display one conflict message when they are all owing to identical - missing depexts [#4678 @dra27] - * Don't exclude base packages from rebuilds (made some sense in opam 2.0 with - base packages but doesn't make sense with 2.1 switch invariants) [#4569 @dra27] - * Don't refer to base packages in messages any more - [#4623 @dra27 - fixes #4572] - * Give the correct command when demonstrating switch creation - [#4675 @dra27 - fixes #4673] - * On switch loading, if invariant is inferred and a write lock required, write - the file [#4638 @rjbou] - * Don't look for lock files for pin depends [#4511 @rjbou - fix #4505] - * Fetch sources when pinning an already-pinned package with a different URL - when using working directory [#4542 @rjbou - fix #4484] - * Don't ask for confirmation for pinning base packages (similarly makes no - sense with 2.1 switch invariants) [#4571 @dra27] - * Fix version pin source retrieving: mustn't error if archive opam file is - malformed [#4580 @rjbou] - * `opam list --silent` renamed to `--check` [#4595 @dra27 - fix #4323] - * Include `doc` field in `opam-show` [#4567 @dra27 - partially fix #4565] - * Fix `switch` global variable resolving [#4685 @rjbou - fix #4684] - * Fix `hash` package variable resolving [#4687 @rjbou] - * Lint: Fix W59 & E60 for conf packages (no URL required) - [#4550 @rjbou - fix #4549] - * Lint: Fix W59 & E60 with VCS URLs, don't check upstream if URL has VCS - backend [#4635 @rjbou] - * Lint: Add E67 checksum specified with non archive URL [#4635 @rjbou] - * Lint: Disable subpath warning E63,W64 [#4638 @rjbou] - * Lint: Fix manpage listing [#4708 @rjbou] - * Don't write lock file with `--read-only`, `--safe`, and `--dryrun` - [#4562 @rjbou - fix #4320] - * Make `opam lock` consistent with `opam install`. On local pin, always take - last opam file even if uncommitted [#4562 @rjbou - fix #4320] - * Opam file: Fix `features` parser [#4507 @rjbou] - * Opam file: Rename `hidden-version` to `avoid-version` [#4527 @dra27] - * Opam file: Fix rewriting with preserved format empty field error - [#4634 @rjbou - fix #4628] - * Opam file: Switch config: Defined `invariant` field as an option to - differentiate when it is not defined [#4638 @rjbou] - * Opam file: Differentiate bad format from bad (opam) version with - `Bad_version` exception, raised from `OpamFormat.check_opam_version` - [#4638 @rjbou] - * Opam file: Always print the `opam-version` field on files [#4638 @rjbou] - * Opam file: Config: add `opam-root-version` field as a marker for the whole - opam root [#4638 @rjbou - fix #4636] - * Opam file: Add `BestEffort` modules with reading functions that don't show - errors, given the `opam_file_format` internal field [#4638 @rjbou - fix #4636] - * Depext: Handle macport variants [#4509 @rjbou - fix #4297] - * Depext: Always upgrade all the installed packages when installing a new - package on Archlinux [#4556 @kit-ty-kate] - * Depext: Handle some additional environment variables (`OPAMASSUMEDEPEXTS`, - `OPAMNODEPEXTS`) [#4587 @AltGr] - * Depext: Improve messages to hint that answering `no` doesn't abort - installation [#4591 @AltGr] - * Depext: Add support for non-interactive mode in MacPorts [#4676 @kit-ty-kate] - * Depext: Handling of packages of tagged repositories for Alpine - [#4700 @rjbou - fix #4670] - * Depext: Clarify some `assume-depexts` related messages - [#4671 @AltGr - partial fix #4662] - * Depext: Warn the user if `epel-release` is missing and unavailable, depexts are - detected [#4679 @dra27 fix #4669] - * Depext: Ignore `config yes` automatic answering when asking confirmation to run - install commands [#4698 @rjbou - fix #4680] - * Sandbox: Fix the conflict with the environment variable name used by Dune - [#4535 @smorimoto - fix ocaml/dune#4166] - * Sandbox: Kill builds on Ctrl-C with bubblewrap - [#4530 @kit-ty-kate - fix #4400] - * Sandbox: Linux: mount existing TMPDIR read-only, re-bind `$TMPDIR` to a - separate TMPFs [#4589 @AltGr] - * Sandbox: Fix the sandbox check [#4589 @AltGr] - * Sandbox: Fix sandbox script shell mistake that made `PWD` read-write on - remove actions [#4589 @AltGr] - * Sandbox: Port bwrap improvements to `sandbox_exec` [#4589 @AltGr] - * Sandbox: Fix `realpath` use for macOS, partial revert of #4589 [#4609 @AltGr] - * Add missing shell quoting to support space and special shell characters in - switch directory path [#4707 @kit-ty-kate] - * Rename `state.cache` to include the `OpamVersion.magic()` string. All `.cache` - files are deleted if any cache file is written to, allowing multiple versions - of the library to coexist without constantly regenerating it - [#4642 @dra27 - fix #4554] - * Fix cuDF preprocessing [#4534 #4627 @AltGr - fix #4624] - * Allow to upgrade to a hidden-version package if a hidden-version package is - already installed [#4525 @kit-ty-kate] - * Add support for a few select criteria useful to CI to the `0install` solver: - `+count[version-lag,solution]` to always choose the oldest version available, - `+removed` to not try to keep installed packages [#4631 @kit-ty-kate] - * Fix `opam-devel`'s tests on platforms without OpenSSL, GNU-diff, and a - system-wide OCaml [#4500 @kit-ty-kate] - * Use Dune to run `reftests` [#4376 @emillon] - * Restrict `extlib` and `dose` version [#4517 @kit-ty-kate] - * Restrict to `opam-file-format.2.1.2` [#4495 @rjbou] - * Require `opam-file-format.2.1.3+` in order to enforce `opam-version: "2.1"` - as first non-comment line [#4639 @dra27 - fix #4394] - * Switch to newer version of MCCS (based on newer GLPK) for `src_ext` - [#4559 @AltGr] - * Bump Dune version to 2.8.2 [#4592 @AltGr] - * Bump the minimal Dune requirement to Dune 1.11 [#4437 @dra27 @kit-ty-kate] - * 4.12 compatibility [#4437 @dra27 @kit-ty-kate] - * Cold compiler updated to 4.12 [#4616 @dra27] - * Fix build from source when a `dune-project` file is presented in the parent - directory [#4545 @kit-ty-kate] - * Fix build from source when a `dune-project` file is presented in the parent - directory [#4545 @kit-ty-kate - fix #4537] - * Fix `opam-devel.install` not to install two files called opam [#4664 @dra27] - * Build release tags as non-dev versions, as for release tarballs - [#4665 @dra27 - fix #4656] - * Disable dev version for tests (needed for format upgrade test) [#4638 @rjbou] - * Add a hint for missing `openssl` in `make cold` [#4702 @rjbou] - * Remove test field from `opam-devel`, they need the network [#4702 @rjbou] - * Update `src_ext` for Dune and MCCS [#4704 @dra27] - * Release scripts: switch to OCaml 4.10.2 by default, add macOS/ARM64 builds by - default [#4559 @AltGr] - * Release scripts: add default CLI version check on full archive build - [#4575 @rjbou] - * Arg: Generalise `mk_tristate_opt` to `mk_state_opt` [#4575 @rjbou] - * Arg: Fix `mk_state_opt` and rename to `mk_enum_opt` [#4626 @rjbou] - * Arg: Add `mk_enum_opt_all` for state flags that appears more than once - [#4582 @rjbou] - * Fix `opam exec` on native Windows when calling Cygwin executables - [#4588 @AltGr] - * Fix temporary file with a too long name causing errors on Windows - [#4590 @AltGr] - * CLI: Add flag deprecation and replacement helper [#4595 @rjbou] - * Win32 Console: fix VT100 support [#3897 #4710 @dra27] - * Tidied the opam files [#4620 @dra27] - * Externalise CLI versioning tools from `OpamArg` into `OpamArgTools` - [#4606 @rjbou] - * Each library defines its own environment variables that fills the config - record [#4606 @rjbou] - * Harden `cygpath` wrapper [#4625 @dra27] - * Reset the plugin `symlinks` when the root is upgraded - [#4641 @dra27 - partial fix for #4619] - * Formalise opam dev version detection with `OpamVersion.is_dev_version` - [#4665 @dra27] - * Add `OpamStd.String.is_prefix_of` [#4694 @rjbou @dra27] - * Fix `OpamStd.Format.pretty_list`: `last` argument dropped if list contains - more than 2 elements [#4694 @rjbou] - * Run the shell hooks with closed `stdin` (bash, zsh) [#4692 @AltGr] - * Improved and extended tests - [#4376 #4504 #4545 #4612 #4668 #4612 #4634 #4672 #4638 #4702 #4697 #4697 - @AltGr @dra27 @emillon @rjbou] - * Improve GitHub Actions - [#4593 #4575 #4610 #4610 #4618 #4606 #4695 #4695 @AltGr @dra27 @rjbou] - * Improve documentation - [#4496 #4506 #4513 #4637 #4681 #4702 - @dannywillems @eth-arm @kit-ty-kate @rjbou @UnixJunkie] ---- diff --git a/data/changelog/opam/2021-06-23-opam-2-1-0-rc2.md b/data/changelog/opam/2021-06-23-opam-2-1-0-rc2.md deleted file mode 100644 index 0b68101e8c..0000000000 --- a/data/changelog/opam/2021-06-23-opam-2-1-0-rc2.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "opam 2.1.0~rc2 released" -authors: [ "David Allsopp" ] -description: "Release announcement for opam 2.1.0~rv2" -tags: [opam, platform] -changelog: | - * Remove OPAMZ3DEBUG evironment variable [#4720 @rjbou - fix #4717] - * Fix format upgrade when there is missing local switches in the config file - [#4715 @rjbou - fix #4713] - * Fix not recorded local switch handling, with format upgrade [#4715 @rjbou] - * Set opam root version to 2.1 [#4715 @rjbou] - * Improved and extended tests [#4715 @rjbou] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-1-0-rc2/8042)!_ - -The opam team has great pleasure in announcing opam 2.1.0~rc2! - -The focus since beta4 has been preparing for a world with more than one released version of opam (i.e. 2.0.x and 2.1.x). The release candidate extends CLI versioning further and, under the hood, includes a big change to the opam root format which allows new versions of opam to indicate that the root may still be read by older versions of the opam libraries. A plugin compiled against the 2.0.9 opam libraries will therefore be able to read information about an opam 2.1 root (plugins and tools compiled against 2.0.8 are unable to load opam 2.1.0 roots). - -Please do take this release candidate for a spin! It is available in the Docker images at ocaml/opam on [Docker Hub](https://hub.docker.com/r/ocaml/opam/tags) as the opam-2.1 command (or you can `sudo ln -f /usr/bin/opam-2.1 /usr/bin/opam` in your `Dockerfile` to switch to it permanently). The release candidate can also be tested via our installation script (see the [wiki](https://github.com/ocaml/opam/wiki/How-to-test-an-opam-feature#from-a-tagged-release-including-pre-releases) for more information). - -Thank you to anyone who noticed the unannounced first release candidate and tried it out. Between tagging and what would have been announcing it, we discovered an issue with upgrading local switches from earlier alpha/beta releases, and so fixed that for this second release candidate. - -Assuming no showstoppers, we plan to release opam 2.1.0 next week. The improvements made in 2.1.0 will allow for a much faster release cycle, and we look forward to posting about the 2.2.0 plans soon! - -# Try it! - -In case you plan a possible rollback, you may want to first backup your -`~/.opam` directory. - -The upgrade instructions are unchanged: - -1. Either from binaries: run - - ``` - bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.1.0~rc2" - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.1.0-rc2) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.1.0-rc2#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -We hope there won't be any, but please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). -Thanks for trying it out, and hoping you enjoy! diff --git a/data/changelog/opam/2022-08-12-opam-2-1-3.md b/data/changelog/opam/2022-08-12-opam-2-1-3.md deleted file mode 100644 index 9f99a68dd7..0000000000 --- a/data/changelog/opam/2022-08-12-opam-2-1-3.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: opam 2.1.3 -authors: [ "Raja Boujbel" ] -description: "Release of opam 2.1.3" -tags: [opam, platform] -changelog: | - * [BUG] Fix `opam init` and `opam init --reinit` when the `jobs` variable has - been set in the opamrc or the current config. [#5056 @rjbou] - * When inferring a 2.1+ switch invariant from 2.0 base packages, don't filter - out pinned packages as that causes very wide invariants for pinned compiler - packages [#5176 @dra27 - fix #4501] - * [BUG] Fix an internal error on repository upgrade from OPAM 1.2 - [#4965 @AltGr] - * Some optimisations to `opam list --installable` queries combined with other - filters [#4882 @AltGr - fix #4311] - * Improve performance of some opam list combinations (e.g. `--available`, - `--installable`) [#4999 @kit-ty-kate] - * Improve performance of `opam list --conflicts-with` when combined with other - filters [#4999 @kit-ty-kate] - * Improve performance of `opam show` by as much as 300% when the package to - show is given explicitly or is unique [#4998 @kit-ty-kate - fix #4997 and - partially #4172] - * [BUG] `opam var` no longer fails if no switch is set - [#5027 @rjbou - fix #5025] - * [BUG] Setting a variable with option `--switch ` fails instead of writing - an invalid `switch-config` file [#5027 @rjbou] - * When a field is defined in switch and global scope, try to determine the - scope also by checking switch selection [#5027 @rjbou] - * [BUG] Handle external dependencies when updating switch state pin status (all - pins), instead as a post pin action (only when called with `opam pin` - [#5047 @rjbou - fix #5046] - * [BUG] When reinstalling a package that has a dirty source, if uncommitted - changes are the same than the ones stored in opam's cache, opam consider that - it is up to date and nothing is updated [4879 @rjbou] - * Stop Zypper from upgrading packages on updates on OpenSUSE - [#4978 @kit-ty-kate] - * Clearer error message if a command doesn't exist - [#4971 @kit-ty-kat - fix #4112] - * [BUG] Remove windows double printing on commands and their output - [#4940 @rjbou] - * Actually allow multiple state caches to co-exist - [#4934 @dra27 - actually fixes #4554] - * Update cold compiler to 4.13 to avoid issues with glibc 2.34 on Unix - [#5017 @dra27] - * Bump opam-file-format to 2.1.4 [#5117 @kit-ty-kate - fix #5116] - * Fix some empty conflict explanations - [#4982 @kit-ty-kate - partially fix #4373] - * Port some tests from master [#4841 #4974 #4861 #4915 #4979 #5004 #5006 #5015 - #5024 #5025 #5031 #5131 #5176 @AltGr @dra27 @kit-ty-kate] - * Update test engine to allow for additional tests [#4913 #4966 #4979 #5004 - #5009 #5024 #5097 @AltGr @kit-ty-kate @rjbou] - * Update for git protocol deprecation on GitHub [#5097 @rjbou] - * When building opam, do not fail if curl/wget is missing [#5223 #5233 @kit-ty-kate] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-1-3/10299)!_ - -We are pleased to announce the minor release of [opam 2.1.3](https://github.com/ocaml/opam/releases/tag/2.1.3). - -This opam release consists of [backported](https://github.com/ocaml/opam/issues/5000) fixes: - * Fix `opam init` and `opam init --reinit` when the `jobs` variable has been set in the opamrc or the current config. ([#5056](https://github.com/ocaml/opam/issues/5056)) - * `opam var` no longer fails if no switch is set ([#5025](https://github.com/ocaml/opam/issues/5025)) - * Setting a variable with option `--switch ` fails instead of writing an invalid `switch-config` file ([#5027](https://github.com/ocaml/opam/issues/5027)) - * Handle external dependencies when updating switch state pin status (all pins), instead as a post pin action (only when called with `opam pin` ([#5046](https://github.com/ocaml/opam/issues/5046)) - * Remove windows double printing on commands and their output ([#4940](https://github.com/ocaml/opam/issues/4940)) - * Stop Zypper from upgrading packages on updates on OpenSUSE ([#4978](https://github.com/ocaml/opam/issues/4978)) - * Clearer error message if a command doesn't exist ([#4112](https://github.com/ocaml/opam/issues/4112)) - * Actually allow multiple state caches to co-exist ([#4554](https://github.com/ocaml/opam/issues/4554)) - * Fix some empty conflict explanations ([#4373](https://github.com/ocaml/opam/issues/4373)) - * Fix an internal error on admin repository upgrade from OPAM 1.2 ([#4965](https://github.com/ocaml/opam/issues/4965)) - -and improvements: - * When inferring a 2.1+ switch invariant from 2.0 base packages, don't filter out pinned packages as that causes very wide invariants for pinned compiler packages ([#4501](https://github.com/ocaml/opam/issues/4501)) - * Some optimisations to `opam list --installable` queries combined with other filters ([#4311](https://github.com/ocaml/opam/issues/4311)) - * Improve performance of some opam list combinations (e.g. `--available`, `--installable`) ([#4999](https://github.com/ocaml/opam/issues/4999)) - * Improve performance of `opam list --conflicts-with` when combined with other filters ([#4999](https://github.com/ocaml/opam/issues/4999)) - * Improve performance of `opam show` by as much as 300% when the package to show is given explicitly or is unique ([#4997](https://github.com/ocaml/opam/issues/4997))([#4172](https://github.com/ocaml/opam/issues/4172)) - * When a field is defined in switch and global scope, try to determine the scope also by checking switch selection ([#5027](https://github.com/ocaml/opam/issues/5027)) - -You can also find API changes in the [release note](https://github.com/ocaml/opam/releases/tag/2.1.3). - ---- - -Opam installation instructions (unchanged): - -1. From binaries: run - - ``` - bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.1.3" - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.1.3) to your PATH. In this case, don't forget to run `opam init --reinit -ni` to enable sandboxing if you had version 2.0.0~rc manually installed or to update you sandbox script. - -2. From source, using opam: - - ``` - opam update; opam install opam-devel - ``` - - (then copy the opam binary to your PATH as explained, and don't forget to run `opam init --reinit -ni` to enable sandboxing if you had version 2.0.0~rc manually installed or to update your sandbox script) - -3. From source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.1.3#compiling-this-repo). - -We hope you enjoy this new minor version, and remain open to [bug reports](https://github.com/ocaml/opam/issues) and [suggestions](https://github.com/ocaml/opam/issues). diff --git a/data/changelog/opam/2023-07-04-opam-2-2-0-alpha.md b/data/changelog/opam/2023-07-04-opam-2-2-0-alpha.md deleted file mode 100644 index 9e8fe81762..0000000000 --- a/data/changelog/opam/2023-07-04-opam-2-2-0-alpha.md +++ /dev/null @@ -1,360 +0,0 @@ ---- -title: opam 2.2.0~alpha -authors: [ - "David Allsopp", - "Léo Andrès", - "Raja Boujbel", - "Basile Clément", - "Kate Deplaix", - "Louis Gesbert", - "Dario Pinto", - "Christine Rose", - "Riku Silvola" -] -description: "Alpha release of opam 2.2.0" -tags: [opam, platform] ---- - - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-2-0-alpha-release/12536)!_ - -We are happy to announce the alpha release of opam 2.2.0. It contains numerous -fixes, enhancements, and updates; including much-improved Windows support, -addressing one of the most important pain points [identified by the OCaml -community](https://discuss.ocaml.org/t/what-are-the-biggest-reasons-newcomers-give-up-on-ocaml/10958). -You can view the full list of changes in the [release -note](https://github.com/ocaml/opam/releases/tag/2.2.0-alpha). - -This alpha release is a significant milestone, brought together by Raja Boujbel -after years of work from the opam dev team (Raja Boujbel, David Allsopp, Kate -Deplaix, Louis Gesbert, in a united OCamlPro/Tarides collaboration) with the -help of many community contributors. We also thank Jane Street for their -continued sponsorship. - -This version is an alpha, so we invite users to test it to spot previously -unnoticed bugs and work towards a stable release. - -## Windows Support - -Opam 2.2 comes with native Windows compatibility. You can now use opam from -your preferred Windows terminal! We rely on the [Cygwin](https://cygwin.com/) -UNIX-like environment for Windows as a compatibility layer, but it is possible -for a package to generate native executables. - -The main opam repository is not Windows compatible at the moment, but existing -work on a [compatible -repository](https://github.com/ocaml-opam/opam-repository-mingw) (originally -from [@fdopen](https://github.com/fdopen)) and [32/64 bit mingw-w64 -packages](https://github.com/dra27/opam-repository) (by -[@dra27](https://github.com/dra27)) is in the process of being merged. Before -the final release, we expect it to be possible to run `opam init` and use the -main opam-repository for Windows. - -### How to Test opam on Windows - -This alpha requires a preexisting Cygwin installation. Support for full -management of a local Cygwin environment inside of opam (so that it's as -transparent as possible) is queued already and should be available in -2.2.0~alpha2 as the default option. - -1. Check that you have all dependencies installed: - * `autoconf`, `make`, `patch`, `curl` - * MinGW compilers: `mingw64-x86_64-gcc-g++`, `mingw64-i686-gcc-g++` - * Or if you want to use the MSVC port of OCaml, you'll need to install Visual Studio or Visual Studio Build Tools -2. Download & extract the [opam archive](https://github.com/ocaml/opam/releases/download/2.2.0-alpha/opam-full-2.2.0-alpha.tar.gz) -3. In the directory launch `make cold` -4. A coffee later, you now have an opam executable! -5. Start your preferred Windows terminal (cmd or PowerShell), and initialise opam with the Windows _sunset_ repository: - * `opam init https://github.com/ocaml-opam/opam-repository-mingw` - -From here, you can try to install [sunset -repository](https://discuss.ocaml.org/t/sunsetting-opam-repository-mingw/11632) -packages. If any bug is found, please [submit an -issue](https://github.com/ocaml-opam/opam-repository-mingw#what-do-i-do-when-things-are-broken). -It will help opam repository maintainers to add Windows repository packages -into the main repository. - -> Hint: if you use the MinGW compiler, don't forget to add to your `PATH` the -path to `libc` dlls (usually -`C:\cygwin64\usr\x86_64-w64-mingw32\sys-root\mingw\bin`). Or compile opam with -`make cold CONFIGURE_ARGS=--with-private-runtime`, and if you change opam -location, don't forget to copy `Opam.Runtime.amd64` (or `Opam.Runtime.i386`) -with it. - - - -## Recursive Pin - -When installing or pinning a package using `opam install` or `opam pin`, opam -normally only looks for opam files at the root of the installed package. With -recursive pinning, you can now instruct opam to also look for `.opam` files in -subdirectories, while maintaining the correct relationship between the `.opam` -files and the package root for versioning and build purposes. - -Recursive pinning is used with the following options to `opam pin` and `opam install`: - * With `--recursive`, opam will look for `.opam` files recursively in all subdirectories. - * With `--subpath `, opam will only look for `.opam` files in the subdirectory ``. - -The two options can be combined: for instance, if your opam packages are stored -as a deep hierarchy in the `mylib` subdirectory of your project, give `opam pin -. --recursive --subpath mylib` a try! - -You can use these options with `opam pin`, `opam install`, and `opam remove`. - -``` -$ tree . -. -├── ba -│   └── z -│   └── z.opam -├── bar -│   └── bar.opam -└── foo.opam - -$ opam pin . --subpath ba/z --no-action -Package z does not exist, create as a NEW package? [y/n] y -z is now subpath-pinned to directory /ba/z in git+file:///tmp/recpin#master (version 0.1) - -$ opam pin --recursive . --no-action -This will pin the following packages: foo, z, bar. Continue? [y/n] y -foo is now pinned to git+file:///tmp/recpin#master (version 0.1) -Package z does not exist, create as a NEW package? [y/n] y -z is now subpath-pinned to directory /ba/z in git+file:///tmp/recpin#master (version 0.1) -Package bar does not exist, create as a NEW package? [y/n] y -bar is now subpath-pinned to directory /bar in file:///tmp/recpin (version 0.1) - -$ opam pin -bar.0.1 (uninstalled) rsync directory /bar in file:///tmp/recpin -foo.0.1 (uninstalled) git git+file:///tmp/recpin#master -z.0.1 (uninstalled) git directory /ba/z in git+file:///tmp/recpin#master - -$ opam pin . --recursive --subpath ba/ --no-action -Package z does not exist, create as a NEW package? [y/n] y -z is now subpath-pinned to directory /ba/z in git+file:///tmp/recpin#master (version 0.1) -``` - -## Tree View - -`opam tree` shows packages and their dependencies with a tree view. It is very -helpful to determine which packages bring which dependencies in your installed -switch. - -``` -$ opam tree cppo -cppo.1.6.9 -├── base-unix.base -├── dune.3.8.2 (>= 1.10) -│ ├── base-threads.base -│ ├── base-unix.base [*] -│ └── ocaml.4.14.1 (>= 4.08) -│ ├── ocaml-base-compiler.4.14.1 (>= 4.14.1~ & < 4.14.2~) -│ └── ocaml-config.2 (>= 2) -│ └── ocaml-base-compiler.4.14.1 (>= 4.12.0~) [*] -└── ocaml.4.14.1 (>= 4.02.3) [*] -``` - -It can also display a reverse-dependency tree (through `opam why`, which is an -alias to `opam tree --rev-deps`). This is useful to examine how dependency -versions get constrained. - -``` -$ opam why cmdliner -cmdliner.1.2.0 -├── (>= 1.1.0) b0.0.0.5 -│ └── (= 0.0.5) odig.0.0.9 -├── (>= 1.1.0) ocp-browser.1.3.4 -├── (>= 1.0.0) ocp-indent.1.8.1 -│ └── (>= 1.4.2) ocp-index.1.3.4 -│ └── (= version) ocp-browser.1.3.4 [*] -├── (>= 1.1.0) ocp-index.1.3.4 [*] -├── (>= 1.1.0) odig.0.0.9 [*] -├── (>= 1.0.0) odoc.2.2.0 -│ └── (>= 2.0.0) odig.0.0.9 [*] -├── (>= 1.1.0) opam-client.2.2.0~alpha -│ ├── (= version) opam.2.2.0~alpha -│ └── (= version) opam-devel.2.2.0~alpha -├── (>= 1.1.0) opam-devel.2.2.0~alpha [*] -├── (>= 0.9.8) opam-installer.2.2.0~alpha -└── user-setup.0.7 -``` - -> Special thanks to [@cannorin](https://github.com/cannorin) for contributing this feature. - -## Recommended Development Tools - -There is now a way for a project maintainer to share their project development -tools: the `with-dev-setup` dependency flag. It is used in the same way as -`with-doc` and `with-test`: by adding a `{with-dev-setup}` filter after a -dependency. It will be ignored when installing normally, but it's pulled in when the -package is explicitely installed with the `--with-dev-setup` flag specified on -the command line. The variable is also resolved in the `post-messages:` field -to allow maintainers to share more informations about that setup. - -This is typically useful for tools that are required for bootstrapping or -regenerating artifacts. - - -For example -``` -opam-version: "2.0" -depends: [ - "ocaml" - "dune" - "ocp-indent" {with-dev-setup} -] -build: [make] -install: [make "install"] -post-messages: -[ "Thanks for installing the package" - "and its tool dependencies too, it will help for your futur PRs" {with-dev-setup} ] -``` - -## Software Heritage Binding - -[Software Heritage](https://www.softwareheritage.org) is a project that aims to -archive all software source code in existence. This is done by collecting -source code with a _loader_ that uploads software source code to the Software -Heritage distributed infrastructure. From there, any project/version is -available via the [search webpage](https://archive.softwareheritage.org/) and -via a unique identifier called the -[SWHID](https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html#uri-scheme). -Some OCaml source code is [already -archived](https://www.softwareheritage.org/2021/04/20/connecting-ocaml/), and -the main opam and Coq repository packages are continuously uploaded. - -Opam now integrates a fallback to Software Heritage archive retrieval, based on -SWHID. If an SWHID URL is present in an opam file, the fallback can be -activated. - -To keep backwards compatibility of opam files, we added a specific Software -Heritage URL syntax to the `url.mirrors:` field, which is used to specify -mirrors of the main URL. Opam 2.2.+ understands this specific syntax as a -Software Heritage fallback URL: `https://swhid.opam.ocaml.org/`. - -``` -url { - src: "https://faili.ng/url.tar.gz" - checksum: "sha512=e2146c1d7f53679fd22df66c9061b5ae4f8505b749513eedc67f3c304f297d92e54f5028f40fb5412d32c7d7db92592eacb183128d2b6b81d10ea716b7496eba" - mirrors: [ - "https//failli.ng/mirror.tar.gz" - "https://swhid.opam.ocaml.org/swh:1:dir:9f2be900491e1dabfc027848204ae01aa88fc71d" - ] -} -``` - -To add a Software Heritage fallback URL to your package, use the -[`swhid`](https://github.com/OCamlPro/swhid) library. Specifically the -[`Compute.directory_identifier_deep`](https://github.com/OCamlPro/swhid/blob/master/src/compute.mli#L12) -function: - -1. Download opam package archive -2. Extract the archive -3. Compute SWHID with `Compute.directory_identifier_deep`. You can use this oneliner in the directory: -```ocaml -ocaml -e '#use "topfind";; #require "digestif.ocaml";; #require "swhid";; Swhid_core.Object.pp Format.std_formatter (Result.get_ok (Swhid.Compute.directory_identifier_deep "."))' -``` - -> Special thanks to [@zapashcanon](https://github.com/zapashcanon) for collaborating on this feature. - -## Formula (Experimental) - -It is now possible to leverage the full expressivity of package dependency -formulas from the command line during switch creation and package operations. - -It is possible to create a switch using a formula. For example, with -`ocaml-variant` or `ocaml-system`, excluding `ocaml-base-compiler`: - -``` -opam switch create ocaml --formula '"ocaml-variants" {>= "4.14.1"} | "ocaml-system"' -``` - -This syntax is brought to install commands. For example, while installing a -package, let's say `genet`, you can specify that you want to install either -`conf-mariadb & mariadb` or `conf-postgresql`: - -``` -opam install genet --formula '["mysql" ("conf-mariadb" & "mariadb" | "conf-postgresql")]' -``` - - -## New Options -Here are several of new options (possibly scripts breaking changes are marked with ✘): - -* `opam pin --current` to fix a package to its current state (disabling pending - reinstallations or removals from the repository). The installed package will - be pinned with the opam file that is stored in opam internal state, the one - that is currently installed. - -* `opam pin remove --all` to remove all the pinned packages from a switch. - -* `opam pin remove pkg.version` now removes the pins on pinned `pkg.version`. - -* `opam exec --no-switch` to remove opam environment from launched command. - -``` -$ export FOOVAR=env -$ opam show foo --field setenv -FOOVAR = "package" -$ opam exec -- env | grep "OPAM_SWITCH\|FOO" -FOOVAR=package -OPAM_SWITCH_PREFIX=~/.opam/env -$ opam exec --no-switch -- env | grep "OPAM_SWITCH\|FOO" -FOOVAR=env -``` - -* `opam source --no-switch` to allow downloading package sources without having - an installed switch (instead of failing). - -* `opam clean --untracked` to remove untracked files interactively remaining - from previous packages removal. - -* `opam switch -`, inspired from `git switch -`, that goes back to the previously - selected global switch. - -* `opam admin add-constraint --packages pkg1,pkg2,pkg3` to select - a subset of packages to apply constraints. - -* ✘ Change `--base` into `--invariant`. `opam switch` _compiler_ column now - contains installed packages that verifies invariant formula, and empty - synopsis shows switch invariant. - -``` -$ opam switch create inv --formula '["ocaml" {>= "4.14.1"} "dune"]' -$ opam switch invariant -["ocaml" {>= "4.14.1"} "dune"] -$ opam list --invariant -# Packages matching: invariant -# Name # Installed # Synopsis -dune 3.8.2 Fast, portable, and opinionated build system -ocaml 5.0.0 The OCaml compiler (virtual package) -$ opam switch list -# switch compiler description -→ inv ocaml-base-compiler.5.0.0,ocaml-options-vanilla.1 ocaml >= 4.14.1 & dune -``` - - - -## Try It! - -In case you plan a possible rollback, you may want to first backup your -`~/.opam` directory. - -The upgrade instructions are unchanged: - -1. From binaries: run -``` -bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.2.0~alpha" -``` -Or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.2.0-alpha) to your PATH. - -2. From source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.2.0-alpha#compiling-this-repo). - -Then run: -``` -opam init --reinit -ni -``` - - -Please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). - -Thanks for trying this new release out, and we're hoping you will enjoy the new features! diff --git a/data/changelog/opam/2023-07-26-opam-2-2-0-alpha2.md b/data/changelog/opam/2023-07-26-opam-2-2-0-alpha2.md deleted file mode 100644 index bcb3bb558b..0000000000 --- a/data/changelog/opam/2023-07-26-opam-2-2-0-alpha2.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: opam 2.2.0~alpha2 -authors: [ - "Raja Boujbel", - "Kate Deplaix", -] -description: "Alpha2 release of opam 2.2.0" -tags: [opam, platform] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-2-0-alpha2-release/12699)!_ - -We are happy to announce the second alpha release of opam 2.2.0. It contains -some fixes and a new feature for Windows. You can view the full list in the -[release note](https://github.com/ocaml/opam/releases/tag/2.2.0-alpha2). - -This version is an alpha. so we invite users to test it for previously -unnoticed bugs to head towards the stable release. - -## Windows Support - -The first alpha came with native Windows compatibility. This second alpha comes -with a simpler initialisation for Windows: we no longer rely on an already present -[Cygwin](https://cygwin.com/) UNIX-like environment for Windows as a -compatibility layer. During initialisation, opam now proposes to embed its own fully -managed Cygwin install. - -The main `opam-repository` Windows compliance is still a work in progress. We -recommend using an existing, [compatible -repository](https://github.com/ocaml-opam/opam-repository-mingw) (originally -from [@fdopen](https://github.com/fdopen)) and [32/64 bit mingw-w64 -packages](https://github.com/dra27/opam-repository) (by -[@dra27](https://github.com/dra27)). - - -### How to Test opam on Windows - -This alpha requires a preexisting Cygwin installation for compiling opam. - -1. Check that you have all dependencies installed: - * `autoconf`, `make`, `patch`, `curl` - * MinGW compilers: `mingw64-x86_64-gcc-g++`, `mingw64-i686-gcc-g++` - * If you want to use the MSVC port of OCaml, you'll need to install Visual Studio or Visual Studio Build Tools -2. Download & extract the [opam archive](https://github.com/ocaml/opam/releases/download/2.2.0-alpha2/opam-full-2.2.0-alpha2.tar.gz) -3. In the directory launch `make cold` -4. A coffee later, you now have an opam executable! -5. Start your preferred Windows terminal (`cmd` or `PowerShell`), and initialise opam with the Windows _sunset_ repository: - * `opam init https://github.com/ocaml-opam/opam-repository-mingw` - -From here, you can try to install the [sunset -repository](https://discuss.ocaml.org/t/sunsetting-opam-repository-mingw/11632) -packages. If you find any bugs, please [submit an -issue](https://github.com/ocaml-opam/opam-repository-mingw#what-do-i-do-when-things-are-broken). -It will help `opam-repository` maintainers to add Windows repository packages -into the main repository. - -> Hint: if you use the MinGW compiler, don't forget to add to your `PATH` the -path to `libc` dlls (usually -`C:\cygwin64\usr\x86_64-w64-mingw32\sys-root\mingw\bin`). You can also compile opam with -`make cold CONFIGURE_ARGS=--with-private-runtime`, and if you change opam's -location, don't forget to copy `Opam.Runtime.amd64` (or `Opam.Runtime.i386`) -with it. - -## Updates & Fixes - * `opam var` now has a more informative error message in case of package variable - * `opam lint`: update Error 29 on package variables on filters to check also `conflicts:` field - * `opam admin lint` cleans output when called not from a terminal - * `configure` throws an error if no complementary compiler is found on Windows - - -## Try It! - -In case you plan a possible rollback, you may want to first backup your -`~/.opam` directory. - -The upgrade instructions are unchanged: - -1. Either from binaries, run - - ``` - bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.2.0~alpha2" - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.2.0-alpha2) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.2.0-alpha2#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -Please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). diff --git a/data/changelog/opam/2023-11-15-opam-2-2-0-alpha3.md b/data/changelog/opam/2023-11-15-opam-2-2-0-alpha3.md deleted file mode 100644 index 4ddb1da98f..0000000000 --- a/data/changelog/opam/2023-11-15-opam-2-2-0-alpha3.md +++ /dev/null @@ -1,153 +0,0 @@ ---- -title: opam 2.2.0~alpha3 -authors: [ - "Raja Boujbel", - "Kate Deplaix", - "David Allsopp", -] -description: "Alpha3 release of opam 2.2.0" -tags: [opam, platform] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-2-0-alpha3/13431)!_ - -We are happy to announce the third alpha release of opam 2.2.0. It contains -some fixes and a new feature for Windows. You can view the full list in the -[release note](https://github.com/ocaml/opam/releases/tag/2.2.0-alpha3). - -This version is an alpha, we invite users to test it to spot previously -unnoticed bugs as we head towards the stable release. - -## Major change: Environment variables handling on Windows - -opam files now support a new `x-env-path-rewrite` field which -specifies rewriting rules for the environment variable updates defined in -the `setenv` and `build-env` fields. This field allows greater control over the -separator character used for PATH-like fields (i.e. `;` vs `:`), conversion of -slashes to backslashes, and even conversion from Windows native path format -(`C:\cygwin64\home\dra\.opam`) to Cygwin format (`/home/dra/.opam`). - -The rewriting rules allow opam directory-like variables (e.g. the `%{lib}%` directory -of a switch) to be used in `setenv` and `build-env` fields in a portable way. - -For example, given: -``` -setenv: [ - [PKG_CONFIG_PATH += "%{lib}%/pkgconfig"] - [PATH += "%{share}%/bin"] -] -x-env-path-rewrite: [ - [ PKG_CONFIG_PATH ":" "host" ] - [ PATH (":" {os != "win32"} | ";" {os = "win32"}) ("target" {os != "win32"} | "target-quoted" {os = "win32"}) ] -] -``` -the environment variable changes given by `opam env` on Windows would be: - -``` -PKG_CONFIG_PATH='/cygdrive/c/Users/DRA/AppData/Local/opam/default/lib/pkgconfig[:]' -PATH='C:\Users\DRA\AppData\Local\opam\default\share\bin;C:\Users\DRA\AppData\Local\opam\default\bin;' -``` - -with the following interesting parts for Windows users: -- `PKG_CONFIG_PATH`, which is consumed by a Cygwin-tool, has the directory given in Unix-like syntax, and opam's `share` variable was automatically converted -- The correct separator is used for each (`:` for `PKG_CONFIG_PATH`, `;` for `PATH` is used when adding entries) -- In the `PATH` update, `/bin` was converted to `\bin` - -*Note that the specification for `PATH` is opam's _default_ behaviour, so it's not actually necessary to have this formula for `PATH` in the `x-env-path-rewrite` field.* - -The full syntax is described in full in the [manual](https://opam.ocaml.org/doc/Manual.html#env-update-rewrite). - -Opam files carrying this new field are still compatible with the opam 2.0 syntax as it is an extension field, however its effect is only available with opam 2.2.0~alpha3 and above. -If you want to make sure users of the package containing it have a compatible opam, you can use the `available` field to that end: -``` -available: opam-version >= "2.2.0~alpha3" -``` -or, if the change is Windows-specific: -``` -available: opam-version >= "2.2.0~alpha3" | os != "win32" -``` - -## Other noteworthy changes - -* Sandbox: `/tmp` is now writable again, restoring POSIX compliance -* opam tree: `opam tree package.version` is now supported, displaying the dependency tree of a specific version of a package -* opam tree: `--recurse` and `--subpath` are supported for directory arguments -* opam admin: new `add-extrafiles` command to add/check/update the `extra-files:` field according to the files present in the `files/` directory -* opam lint: new syntax allow marking a set of warnings as errors e.g. `-W @1..9` -* Releases: Pre-built binaries now include ppc64le and s390x - -## Miscellaneous changes - -* A handful of issues related to the compilation of opam on Windows were fixed -* Bugs in the handling of the `OPAMCURL`, `OPAMFETCH` and `OPAMVERBOSE` environment variables were fixed -* Bugs in the handling of the `--assume-built` argument were fixed -* Sporadic crashes and segfaults during shell detection on Windows were fixed - -Various other improvements were made and bugs were fixed. -API changes are denoted in the release note linked above. -This release also includes a handful of PRs improving the documentation and more than a dozen PRs improving and extending the tests. - -## Windows Support - -The main opam-repository Windows compliance is still a work in progress, we -recommend to use existing [compatible -repository](https://github.com/ocaml-opam/opam-repository-mingw) (originally -from [@fdopen](https://github.com/fdopen)) and [32/64 bit mingw-w64 -packages](https://github.com/dra27/opam-repository/tree/windows-5.0) (by -[@dra27](https://github.com/dra27)). - - -### How to Test opam on Windows -If you're feeling adventurous, you can use the experimental pre-built binary for Windows available [here](https://github.com/ocaml/opam/releases/download/2.2.0-alpha3/opam-2.2.0-alpha3-preview-for-windows.exe). It should work but since it's our first public pre-built binary for Windows please use at your own risk. - -Otherwise you can compile opam yourself using the following steps: - -This alpha requires a preexisting Cygwin installation for compiling opam. - -1. Check that you have all dependencies installed: - * `autoconf`, `make`, `patch`, `curl` - * MinGW compilers: `mingw64-x86_64-gcc-g++`, `mingw64-i686-gcc-g++` - * Or if you want to use the MSVC port of OCaml, you'll need to install Visual Studio or Visual Studio Build Tools -2. Download & extract the [opam archive](https://github.com/ocaml/opam/releases/download/2.2.0-alpha3/opam-full-2.2.0-alpha3.tar.gz) -3. In the directory: - * if you are using MSVC: launch `make cold` - * if you are using MinGW: make sure the path to the `libc` dlls are in your `PATH` and launch `make cold`. For instance: `export PATH='C:\cygwin64\usr\x86_64-w64-mingw32\sys-root\mingw\bin':$PATH && make cold`. Don’t forget to update `PATH` accordingly or place the `opam` binary in the same directory as the `libc` dlls if you want to move the resulting opam binary. - * alternatively, if you're using MinGW: `make cold CONFIGURE_ARGS=--with-private-runtime`. If you change the location of the resulting opam binary, don't forget to copy `Opam.Runtime.amd64` directory (or `Opam.Runtime.i386`) in the same directory. -4. A coffee later, you now have an opam executable! -5. Start your preferred Windows terminal (`cmd` or `PowerShell`), and initialise opam with the Windows _sunset_ repository: - * `opam init git+https://github.com/ocaml-opam/opam-repository-mingw` - -From here, you can try to install the [sunset -repository](https://discuss.ocaml.org/t/sunsetting-opam-repository-mingw/11632) -packages. If you find any bugs, please [submit an -issue](https://github.com/ocaml-opam/opam-repository-mingw#what-do-i-do-when-things-are-broken). -It will help opam-repository maintainers to add Windows repository packages -into the main repository. - -## Try it! - -In case you plan a possible rollback, you may want to first backup your -`~/.opam` directory. - -The upgrade instructions are unchanged: - -1. Either from binaries: run - - ``` - bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.2.0~alpha3" - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.2.0-alpha3) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.2.0-alpha3#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -Please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). - -Thanks for trying this new release out, and we hope you will enjoy the new features! diff --git a/data/changelog/opam/2024-01-18-opam-2-2-0-beta1.md b/data/changelog/opam/2024-01-18-opam-2-2-0-beta1.md deleted file mode 100644 index 38ada53168..0000000000 --- a/data/changelog/opam/2024-01-18-opam-2-2-0-beta1.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: opam 2.2.0~beta1 -authors: [ - "Raja Boujbel", - "Kate Deplaix", - "David Allsopp", -] -description: "Beta1 release of opam 2.2.0" -tags: [opam, platform] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-2-0-beta1/13913)!_ - -We are happy to announce the first beta release of opam 2.2.0. It contains -some fixes and a new feature for Windows. You can view the full list in the -[release note](https://github.com/ocaml/opam/releases/tag/2.2.0-beta1). - -This version is a beta, we invite users to test it to spot previously -unnoticed bugs as we head towards the stable release. - -## Major change: Check and advertise to use Git for Windows - -Opam 2.2 is based on a Cygwin installation (previously installed, or managed -internally by opam). Cygwin's Git has three known usability issues when used -outside a Cygwin environment: it uses a different set of trusted certificate -authorities, has its own Credential Manager and potentially uses a separate Git -configuration. We therefore recommend using [Git for -Windows](https://gitforwindows.org) either installed manually or via `winget`. - -At `opam init`, opam checks for available Git(s), and asks the user to choose -one of the available, or to rerun `opam init` after installing another Git. - -## Other noteworthy changes - -* When compiling opam on Windows with MinGW, the resulting opam binary now contains `libstdc++` instead of requiring the DLL to be distributed alongside it or present in the environment -* Fix `opam env` containing carriage return on Cygwin - `eval $(opam env)` now works from a Cygwin bash terminal - -## Miscellaneous changes - -* Remove stray comments from `pwsh` and `cmd` opam env output -* Add `./configure --enable-static` to compile the opam binary statically on Linux -* Fix debug logs showing up regardless of verbosity on macOS 12.7.1 / 13.6.3 / 14.2 and FreeBSD -* Upgrade to, and require mccs >= 1.1+17 -* Fix `opam tree` options `--dev` and `--no-switch` - -Various other improvements were made and bugs were fixed. -API changes are denoted in the release note linked above. -This release also includes PRs improving the documentation and improving and extending the tests. - -## Windows Support - -The main opam-repository Windows compliance is still a work in progress, we -recommend to use existing [compatible -repository](https://github.com/ocaml-opam/opam-repository-mingw) (originally -from [@fdopen](https://github.com/fdopen)) and [32/64 bit mingw-w64 -packages](https://github.com/dra27/opam-repository/tree/windows-5.0) (by -[@dra27](https://github.com/dra27)). - - -### How to Test opam on Windows - -If you're feeling adventurous, you can use the experimental pre-built binary for Windows available [here](https://github.com/ocaml/opam/releases/download/2.2.0-beta1/opam-2.2.0-beta1-x86_64-preview-for-windows.exe). - -Otherwise you can compile opam yourself using the following steps: - -This beta requires a preexisting Cygwin installation for compiling opam. - -1. Check that you have all dependencies installed: - * `autoconf`, `make`, `patch`, `curl` - * MinGW compilers: `mingw64-x86_64-gcc-g++`, `mingw64-i686-gcc-g++` - * Or if you want to use the MSVC port of OCaml, you'll need to install Visual Studio or Visual Studio Build Tools -2. Download & extract the [opam archive](https://github.com/ocaml/opam/releases/download/2.2.0-beta1/opam-full-2.2.0-beta1.tar.gz) -3. In the directory, launch `make cold` -4. A coffee later, you now have an opam executable! -5. Start your preferred Windows terminal (`cmd` or `PowerShell`), and initialise opam with the Windows _sunset_ repository: - * `opam init git+https://github.com/ocaml-opam/opam-repository-mingw` - -From here, you can try to install the [sunset -repository](https://discuss.ocaml.org/t/sunsetting-opam-repository-mingw/11632) -packages. If you find any bugs, please [submit an -issue](https://github.com/ocaml-opam/opam-repository-mingw#what-do-i-do-when-things-are-broken). -It will help opam-repository maintainers to add Windows repository packages -into the main repository. - -## Try it! - -In case you plan a possible rollback, you may want to first backup your -`~/.opam` directory. - -The upgrade instructions are unchanged: - -1. Either from binaries: run - - ``` - bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.2.0~beta1" - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.2.0-beta1) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.2.0-beta1#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -Please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). - -Thanks for trying this new release out, and we hope you will enjoy the new features! diff --git a/data/changelog/opam/2024-04-09-opam-2.2.0-beta2.md b/data/changelog/opam/2024-04-09-opam-2.2.0-beta2.md deleted file mode 100644 index 960340153a..0000000000 --- a/data/changelog/opam/2024-04-09-opam-2.2.0-beta2.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: opam 2.2.0~beta2 -authors: [ - "Raja Boujbel", - "Kate Deplaix", - "David Allsopp", -] -description: "Beta2 release of opam 2.2.0" -tags: [opam, platform] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-2-0-beta2/14461)!_ - -We are indescribably thrilled to announce the second beta release of opam 2.2.0. - -It contains everything required to be able to make opam-repository compatible -with Windows, as well as a whole bunch of fixes. You can view the full list -of changes in the -[release note](https://github.com/ocaml/opam/releases/tag/2.2.0-beta2). - -**We'll post another blog post very soon with more directions on how to test -opam on Windows with this release.** - -This version is a beta, we invite users to test it to spot previously -unnoticed bugs as we head towards the stable release. - -## Changes - -### Windows support - -This beta introduces a handful of changes necessary to be able to -make the default opam-repository support Windows out of the box: - -* Add a new `sys-ocaml-system` init default global eval variable -* Hijack the `"%{var?string-if-true:string-if-false-or-undefined}%"` syntax to - support extending the variables of packages with + in their name - (`conf-c++` and `conf-g++` already exist) using `"%{?pgkname:var:}%"` -* Add `winsymlinks:native` to the `CYGWIN` environment variable when installing - a package on Windows. In particular, this provides a workaround when extracting - ocamlbuild's sources. -* Internal Cygwin installation's bin directory is placed as far down `PATH` as - is necessary not to shadow `bash`, `tar`, `sort` or `git` -* Disable ACL in Cygwin internal install to avoid permission mismatch errors - -We expect to be able to show the proposed changed to opam-repository -very soon to take advantage of all these changes. - -### opam-repository scalability - -The current draft resolution resulting from the discussion in -[ocaml/opam-repository#23789](https://github.com/ocaml/opam-repository/issues/23789) -about the scalability of opam-repository includes the removal of some -packages. However currently, opam uses the `patch` system command to apply -changes from a repository. The behaviour of that command is thus very -important and it is a known behaviour for the macOS and BSDs `patch` -command to not be able to delete files which leads to failures and -inconsistencies for opam. Package managers on those platforms installing -opam already make opam depend on GNU patch, however a certain number of -people do not install opam via a system package manager (e.g. our own install script!) -and end up using their system version of `patch`. This is in particular -a problem on macOS as the name of the GNU patch command is not `gpatch` like -on BSDs but simply `patch` when installed via Homebrew. - -This issue is surprisingly tricky to fix, and after many trials and errors, -we've decided to: - -* Warn if GNU patch is not detected when a patch is applied -* Use `gpatch` by default instead of `patch` on NetBSD and DragonFlyBSD -* Use `gpatch` if it exists and is detected as GNU patch when `patch` is not - GNU patch - -These changes will make their way to the upcoming opam 2.1.6, in a few weeks. - -### Other noteworthy changes - -* Recommend enabling Developer Mode on Windows. - This allows the creation of symlinks without requiring elevation. - Longer-term, the aim is that we should never _require_ Developer Mode, - but at the moment more things work with it than without it! -* Mark the internal Cygwin installation as recommended. - Please don't try to maintain your own Cygwin install - for use with opam unless you really know what you're doing! -* Fix MSYS2 support. For 2.2.0, the focus has been on Cygwin, - so configuring opam to use MSYS2 is quite manual. - Please note that even if opam can use a MSYS2 installation, - it is not yet officially supported and opam repository is not - yet MSYS2 compatible. Use opam with MSYS2 only if you - _really really_ know what you're doing! -* Fix issues when using fish -* Improve the internal Cygwin installation during init on Windows -* Unixify Windows paths in init shells scripts -* Disable Software Heritage fallback by default as there currently no CI job - in opam-repository to check validity of proposed `swhid` regarding release - archive (neither publication tools support) and some concerns were raised - regarding the degree of trust of the hashing method used by Software - Heritage (sha1). -* Make sure `opam source --dev` with git sources, clones the whole repository - instead of using `--depth=1` -* Sandbox: Mark the user temporary directory - (as returned by `getconf DARWIN_USER_TEMP_DIR`) as writable when TMPDIR - is not defined on macOS -* Add Warning 69: Warn for new syntax when package name in variable in string - interpolation contains several '+' (this is related to the "hijack" item above) -* Add support for Wolfi OS, treat it like Alpine family as it also uses apk -* Upgrade the vendored dune package to 3.14.2 to allow to compile opam when - the environment contains unicode characters on Windows (in particular, - this means opam now works if your username contains accented characters) -* Upgrade other vendored packages - (cmdliner 1.2.0, re 1.11.0, ocamlgraph 2.1.0, opam-file-format 2.1.6) - -Various other general and performance improvements were made and bugs were fixed. -API changes are denoted in the -[release note](https://github.com/ocaml/opam/releases/tag/2.2.0-beta2). -This release also includes PRs improving the documentation and improving -and extending the tests. - -## Windows Support - -As we've said above we're writing a separate blog post to present how to test -this new release of opam on Windows. - -Stay tuned! - -## Try it! - -In case you plan a possible rollback, you may want to first backup your -`~/.opam` directory. - -The upgrade instructions are unchanged: - -1. Either from binaries: run - - ``` - bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.2.0~beta2" - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.2.0-beta2) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.2.0-beta2#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -Please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). - -Thanks for trying this new release out, and we hope you will enjoy the new features! diff --git a/data/changelog/opam/2024-06-10-opam-2-2-0-beta3.md b/data/changelog/opam/2024-06-10-opam-2-2-0-beta3.md deleted file mode 100644 index 1aa20be4b2..0000000000 --- a/data/changelog/opam/2024-06-10-opam-2-2-0-beta3.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: opam 2.2.0~beta3 -authors: [ - "Raja Boujbel", - "Kate Deplaix", - "David Allsopp", -] -description: "Beta3 release of opam 2.2.0" -tags: [opam, platform] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-2-0-beta3/14772)!_ - -We are very pleased to announce the third and final beta release of opam 2.2.0. - -We've done our best to polish everything and squash as many bugs as possible in order -to be ready for the final release. You can view the full list of changes in the -[release note](https://github.com/ocaml/opam/releases/tag/2.2.0-beta3). - -This version is a beta, we invite users to test it to spot previously -unnoticed bugs as we near the stable release. - -## Changes - -* Greatly enhance the opam init user experience on Windows, and the number - of recognised configurations -* New option `opam init --cygwin-extra-packages=CYGWIN_PKGS --cygwin-internal-install`, - to specify additional packages for the internal Cygwin installation -* Redirect the opam root to `C:\opamroot\opam-xxx` when the opam root contains spaces on Windows -* Out-of-the-box UTF-8 paged `--help` on Windows -* Fix a performance regression when calling `opam install --deps-only` on an already installed package -* Fix several edge cases related to environment reverting -* Fixed some issues that could appear when upgrading from previous versions of opam -* Fix various issues with `opam tree --with-test` -* Fix parsing opam 2.1 switch import files containing extra-files -* Fix download URLs containing invalid characters on Windows -* Fix some failure cases when extracting tarballs which contain symlinks on Windows - -Various other general and performance improvements were made and bugs were fixed. -API changes are denoted in the -[release note](https://github.com/ocaml/opam/releases/tag/2.2.0-beta3). -This release also includes PRs improving the documentation and improving -and extending the tests. - -## Try it on Windows! - -**BEWARE: the command shown below is experimental, use caution and please do report any issues that you are experiencing. If you prefer to not use our experimental script, feel free to get the Windows binary directly from [the Release Page](https://github.com/ocaml/opam/releases/tag/2.2.0-beta3) and put it in your directory of choice instead.** - -Now that the [Windows support was merged in opam-repository](https://github.com/ocaml/opam-repository/pull/25861), -testing is as simple as calling the following command from a PowerShell terminal: -``` -Invoke-Expression "& { $(Invoke-RestMethod https://raw.githubusercontent.com/kit-ty-kate/opam/windows-installer/shell/install.ps1) }" -``` -opening a new terminal, and a simple `opam init` will work out-of-the-box. - -## Try it on other platforms! - -In case you plan a possible rollback, you may want to first backup your -`~/.opam` directory. - -The upgrade instructions are unchanged: - -1. Either from binaries: run - - ``` - bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.2.0~beta3" - ``` - - or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.2.0-beta3) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.2.0-beta3#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -Please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). - -Thanks for trying this new release out, and we hope you will enjoy the new features! diff --git a/data/changelog/opam/2024-06-21-opam-2-2-0-rc1.md b/data/changelog/opam/2024-06-21-opam-2-2-0-rc1.md deleted file mode 100644 index c2b7a02e7b..0000000000 --- a/data/changelog/opam/2024-06-21-opam-2-2-0-rc1.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: opam 2.2.0~rc1 -authors: [ - "Raja Boujbel", - "Kate Deplaix", - "David Allsopp", -] -description: "RC1 release of opam 2.2.0" -tags: [opam, platform] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-2-0-rc1-release/14842)!_ - -We are very excited to announce the first (and hopefully only) release candidate for opam 2.2.0. - -We've squashed a few more bugs and we consider this to be ready for the final release. You can view the full list of changes in the [release note](https://github.com/ocaml/opam/releases/tag/2.2.0-rc1). - -We invite users to test it one final time just in case there are any previously unnoticed bugs! - -## Changes - -* Fix `opam upgrade` wanting to keep rebuilding the compiler (as now it contains an `x-env-path-rewrite` field) -* Provide defaults so `opam init -y` no longer asks questions on Windows -* Fix `OpamConsole.menu` when there are more than 9 options (can happen on Windows) - -A couple more improvements were made and bugs were fixed. -The single API change is also denoted in the -[release note](https://github.com/ocaml/opam/releases/tag/2.2.0-rc1). -This release also includes PRs extending the tests. - -## Try it! - -In case you plan a possible rollback, you may want to first backup your -`~/.opam` or `$env:LOCALAPPDATA\opam` directory. - -The upgrade instructions are unchanged: - -1. Either from binaries: run - -For Unix systems -``` -bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.2.0~rc1" -``` -or from PowerShell for Windows systems -``` -Invoke-Expression "& { $(Invoke-RestMethod https://opam.ocaml.org/install.ps1) }" -``` -or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.2.0-rc1) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.2.0-rc1#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -Please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). - -Thanks for trying this new release out, and we hope you will enjoy the new features of opam 2.2! diff --git a/data/changelog/opam/2024-09-19-opam-2-3-0-alpha1.md b/data/changelog/opam/2024-09-19-opam-2-3-0-alpha1.md deleted file mode 100644 index 2b952b0a67..0000000000 --- a/data/changelog/opam/2024-09-19-opam-2-3-0-alpha1.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: "opam 2.3.0~alpha1" -authors: [ - "Raja Boujbel", - "Kate Deplaix", - "David Allsopp", -] -description: "Release of opam 2.3.0~alpha1" -tags: [opam, platform] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-3-0-alpha1/15325)!_ - -As mentioned in [our talk at the OCaml Workshop 2024](https://icfp24.sigplan.org/details/ocaml-2024-papers/10/Opam-2-2-and-beyond), -we decided to switch to a time-based release cycle (every 6 months), starting with opam 2.3. - -As promised, we are happy to announce the first alpha release of opam 2.3.0. -You can view the full list of changes in the -[release note](https://github.com/ocaml/opam/releases/tag/2.3.0-alpha1). - -This version is an alpha, we invite users to test it to spot previously -unnoticed bugs as we head towards the stable release. - -## Major breaking change - -When loading a repository, opam now ignores files in packages' `files/` directories which aren't listed in the `extra-files` field of the opam file. -This was done to simplify the opam specification where we hope the opam file to be the only thing that you have to look at when reading a package specification. The optionality of the `extra-files:` field goes against that principle. This change also reduces the surface area for potential file corruption as it ensures that extra-files are checked against their checksums. - -This is a breaking change and means that if you are using the `files/` directory without the `extra-files:` field, you need to make sure that all files in that directory are listed in the `extra-files` field. -Once done, the resulting opam file is backward-compatible and you don't need to worry about anything else. - -If you have an opam repository, you should make sure all files are listed so every packages continues to work without any issue, which can be done automatically using the `opam admin update-extrafiles` command. - -## Major changes - -* Packages requiring an unsupported version of opam are now marked unavailable, instead of causing a repository error. This means an opam repository can now allow smoother upgrade in the future where some packages can require a newer version of opam without having to fork the repository to upgrade every package to that version as was done for the upgrade from opam 1.2 to 2.0 - -* Add a new `opam list --latests-only` option to list only the latest versions of packages. Note that this option is respects the order options were given on the command line. For example: `--available --latests-only` will first list all the available packages, then choose only the latest packages in that set; while `--latests-only --available` will first list all the latest packages, then only show the ones that are available in that set - -* Fix and improve `opam install --check`, which now checks if the whole dependency tree of the package is installed instead of only the root dependencies - -* Add a new `--verbose-on` option to enable verbose output for specified package names. *Thanks to [@desumn](https://github.com/desumn) for this contribution* - -* Add a new `opam switch import --deps-only` option to install only the dependencies of the root packages listed in the opam switch export file - -* `opam switch list-available` will now not display compilers flagged with `avoid-version`/`deprecated` unless `--all` is given, meaning that the "trunk" build of OCaml no longer appears to be the latest version - -* `opam switch create --repos` now accepts git URLs suffixed with `.git` instead of requiring the `git+https://` protocol prefix. This is consistant with other commands such as `opam repository add`. *Thanks to [@Keryan-dev](https://github.com/Keryan-dev) for this contribution* - -* `opam switch set-invariant` now displays the switch invariant using the same syntax as the `--invariant` flag - -* The `builtin-0install` solver was improved and should now be capable of being your default solver instead of `builtin-mccs+glpk`. It was previously mostly only suited for automated tasks such as Continuous Integration. If you wish to give it a try, simply call `opam option solver=builtin-0install` - -* Most of the unhelpful conflict messages were fixed - -* Fix the value of the `arch` variable when the current OS is 32bit on a 64bit machine (e.g. Raspberry Pi OS) - -* opam now fails when git submodules fail to update instead of ignoring the error and just showing a warning - -* opam's libraries now compile with OCaml >= 5.0 on Windows - -Various performance and other improvements were made and bugs were fixed. -API changes are denoted in the release note linked above. -This release also includes a handful of PRs improving the documentation and more two dozen PRs improving and extending the tests. - -## Try it! - -The upgrade instructions are unchanged: - -1. Either from binaries: run - -For Unix systems -``` -bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.3.0~alpha1" -``` -or from PowerShell for Windows systems -``` -Invoke-Expression "& { $(Invoke-RestMethod https://opam.ocaml.org/install.ps1) } -Version 2.3.0~alpha1" -``` -or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.3.0-alpha1) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.3.0-alpha1#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -Please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). - -Happy hacking! diff --git a/data/changelog/opam/2024-10-15-opam-2-3-0-beta1.md b/data/changelog/opam/2024-10-15-opam-2-3-0-beta1.md deleted file mode 100644 index fbdbf068c1..0000000000 --- a/data/changelog/opam/2024-10-15-opam-2-3-0-beta1.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: "opam 2.3.0~beta1" -authors: [ - "Raja Boujbel", - "Kate Deplaix", - "David Allsopp", -] -description: "Release of opam 2.3.0~beta1" -tags: [opam, platform] ---- - -_Feedback on this post is welcome on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-3-0-beta1/15450)!_ - -We're happy to announce the first beta release of opam 2.3.0. -Compared to the previous 2.3.0\~alpha1 release, you can view the full list of changes in the -[release note](https://github.com/ocaml/opam/releases/tag/2.3.0-beta1). - -This version is a beta, so we invite users to test it to spot previously -unnoticed bugs as we head towards the stable release. - -## Changes - -* Fix an opam 2.1 regression where the initial pin of a local VCS directory would store untracked and ignored files. - Those files would usually be cleaned before building the package; however, Git submodules would not be cleaned and would cause issues when paired with the new behaviour added in 2.3.0\~alpha1, which makes an opam error when Git submodules fail to update (it was previously a warning). ([#5809](https://github.com/ocaml/opam/issues/5809)) - -* Fix a regression which would make opam crash on platforms where `getconf LONG_BIT` is not available (e.g., OpenBSD). ([#6215](https://github.com/ocaml/opam/issues/6215)) - -* Fix the installed packages internal cache, which was storing the wrong version of the opam file after a build failure. - This could be triggered easily for users with custom repositories with non-populated extra-files. ([#6213](https://github.com/ocaml/opam/pull/6213)) - -* Fix a regression in lint W59 with local URLs that are not archives. ([#6218](https://github.com/ocaml/opam/issues/6218)) - -* Fix the compilation of opam on Windows with OCaml >= 5.0 (again) - -* Several improvements to the prebuilt release binaries were made: - * The Linux binaries are now built on Alpine 3.20 - * The FreeBSD binary is now built on FreeBSD 14.1 - * The OpenBSD binary is now built on OpenBSD 7.6 and loses support for OpenBSD 7.5 and older - * A Linux/riscv64 binary is now available - -API changes are denoted in the release note linked above. -This release also includes a couple of PRs improving and extending the tests. - -## Try It! - -The upgrade instructions are unchanged: - -1. Either from binaries: run - -For Unix systems -``` -bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.3.0~beta1" -``` -or from PowerShell for Windows systems -``` -Invoke-Expression "& { $(Invoke-RestMethod https://opam.ocaml.org/install.ps1) } -Version 2.3.0~beta1" -``` -or download manually from [the GitHub "Releases" page](https://github.com/ocaml/opam/releases/tag/2.3.0-beta1) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.3.0-beta1#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -Please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). - -Happy hacking! diff --git a/data/changelog/opam/2024-10-24-opam-2-3-0-beta2.md b/data/changelog/opam/2024-10-24-opam-2-3-0-beta2.md deleted file mode 100644 index 806c585285..0000000000 --- a/data/changelog/opam/2024-10-24-opam-2-3-0-beta2.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: "opam 2.3.0~beta2" -authors: [ - "Raja Boujbel", - "Kate Deplaix", - "David Allsopp", -] -description: "Release of opam 2.3.0~beta2" -tags: [opam, platform] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-3-0-beta2/15496)!_ - -We're happy to announce the second beta release of opam 2.3.0. - -As this version is a beta, we invite users to test it to spot previously -unnoticed bugs as we head towards the stable release. - -## Changes - -Compared to the previous 2.3.0~beta1 release, the main change is: - -* Fix a regression in the detection of the current terminal size that leads to opam output that tries to fit itself into 80 columns regardless of the current terminal size ([#6243](https://github.com/ocaml/opam/issues/6243)). - -* A NetBSD/x86_64 pre-built release binary is now available - -You can view the full list of changes, including API changes, in the -[release note](https://github.com/ocaml/opam/releases/tag/2.3.0-beta2). - -## Try it! - -The upgrade instructions are unchanged: - -1. Either from binaries: run - -For Unix systems -``` -bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.3.0~beta2" -``` -or from PowerShell for Windows systems -``` -Invoke-Expression "& { $(Invoke-RestMethod https://opam.ocaml.org/install.ps1) } -Version 2.3.0~beta2" -``` -or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.3.0-beta2) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.3.0-beta2#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -Please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). - -Happy hacking! diff --git a/data/changelog/opam/2024-10-30-opam-2-3-0-rc1.md b/data/changelog/opam/2024-10-30-opam-2-3-0-rc1.md deleted file mode 100644 index 8291b8b004..0000000000 --- a/data/changelog/opam/2024-10-30-opam-2-3-0-rc1.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: "opam 2.3.0~rc1" -authors: [ - "Raja Boujbel", - "Kate Deplaix", - "David Allsopp", -] -description: "Release of opam 2.3.0~rc1" -tags: [opam, platform] ---- - -_Feedback on this post is welcomed on [Discuss](https://discuss.ocaml.org/t/ann-opam-2-3-0-rc1/15533)!_ - -We're happy to announce the first and hopefully only release candidate of opam 2.3.0. - -This version does not have any significant change compared to the previous 2.3.0~beta2 release -and we hope the final release to also have no significant change. -Regardless, we invite users to test this version to make sure there isn't any regressions. - -Unless a regression is spotted or another problem arises, we hope to have the final release of 2.3.0 out on the 12th of November. - -## Try it! - -The upgrade instructions are unchanged: - -1. Either from binaries: run - -For Unix systems -``` -bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.3.0~rc1" -``` -or from PowerShell for Windows systems -``` -Invoke-Expression "& { $(Invoke-RestMethod https://opam.ocaml.org/install.ps1) } -Version 2.3.0~rc1" -``` -or download manually from [the Github "Releases" page](https://github.com/ocaml/opam/releases/tag/2.3.0-rc1) to your PATH. - -2. Or from source, manually: see the instructions in the [README](https://github.com/ocaml/opam/tree/2.3.0-rc1#compiling-this-repo). - - -You should then run: -``` -opam init --reinit -ni -``` - - -Please report any issues to [the bug-tracker](https://github.com/ocaml/opam/issues). - -Happy hacking! diff --git a/data/changelog/dune/2024-08-26-closing-on-public-beta.md b/data/changelog/posts/dune/2024-08-26-closing-on-public-beta.md similarity index 100% rename from data/changelog/dune/2024-08-26-closing-on-public-beta.md rename to data/changelog/posts/dune/2024-08-26-closing-on-public-beta.md diff --git a/data/changelog/dune/2024-09-25-call-for-feedback.md b/data/changelog/posts/dune/2024-09-25-call-for-feedback.md similarity index 100% rename from data/changelog/dune/2024-09-25-call-for-feedback.md rename to data/changelog/posts/dune/2024-09-25-call-for-feedback.md diff --git a/data/changelog/dune/2024-10-29-shell-completions-in-dune-developer-preview.md b/data/changelog/posts/dune/2024-10-29-shell-completions-in-dune-developer-preview.md similarity index 100% rename from data/changelog/dune/2024-10-29-shell-completions-in-dune-developer-preview.md rename to data/changelog/posts/dune/2024-10-29-shell-completions-in-dune-developer-preview.md diff --git a/data/changelog/dune/2024-11-15-installing-developer-tools-with-dune.md b/data/changelog/posts/dune/2024-11-15-installing-developer-tools-with-dune.md similarity index 100% rename from data/changelog/dune/2024-11-15-installing-developer-tools-with-dune.md rename to data/changelog/posts/dune/2024-11-15-installing-developer-tools-with-dune.md diff --git a/data/changelog/dune-release/2018-04-14-dune-release-0.1.0.md b/data/changelog/releases/dune-release/2018-04-14-dune-release-0.1.0.md similarity index 100% rename from data/changelog/dune-release/2018-04-14-dune-release-0.1.0.md rename to data/changelog/releases/dune-release/2018-04-14-dune-release-0.1.0.md diff --git a/data/changelog/dune-release/2018-06-09-dune-release-0.2.0.md b/data/changelog/releases/dune-release/2018-06-09-dune-release-0.2.0.md similarity index 100% rename from data/changelog/dune-release/2018-06-09-dune-release-0.2.0.md rename to data/changelog/releases/dune-release/2018-06-09-dune-release-0.2.0.md diff --git a/data/changelog/dune-release/2018-07-10-dune-release-0.3.0.md b/data/changelog/releases/dune-release/2018-07-10-dune-release-0.3.0.md similarity index 100% rename from data/changelog/dune-release/2018-07-10-dune-release-0.3.0.md rename to data/changelog/releases/dune-release/2018-07-10-dune-release-0.3.0.md diff --git a/data/changelog/dune-release/2018-09-23-dune-release-1.0.0.md b/data/changelog/releases/dune-release/2018-09-23-dune-release-1.0.0.md similarity index 100% rename from data/changelog/dune-release/2018-09-23-dune-release-1.0.0.md rename to data/changelog/releases/dune-release/2018-09-23-dune-release-1.0.0.md diff --git a/data/changelog/dune-release/2018-09-24-dune-release-1.0.1.md b/data/changelog/releases/dune-release/2018-09-24-dune-release-1.0.1.md similarity index 100% rename from data/changelog/dune-release/2018-09-24-dune-release-1.0.1.md rename to data/changelog/releases/dune-release/2018-09-24-dune-release-1.0.1.md diff --git a/data/changelog/dune-release/2018-10-17-dune-release-1.1.0.md b/data/changelog/releases/dune-release/2018-10-17-dune-release-1.1.0.md similarity index 100% rename from data/changelog/dune-release/2018-10-17-dune-release-1.1.0.md rename to data/changelog/releases/dune-release/2018-10-17-dune-release-1.1.0.md diff --git a/data/changelog/dune-release/2019-04-09-dune-release-1.2.0.md b/data/changelog/releases/dune-release/2019-04-09-dune-release-1.2.0.md similarity index 100% rename from data/changelog/dune-release/2019-04-09-dune-release-1.2.0.md rename to data/changelog/releases/dune-release/2019-04-09-dune-release-1.2.0.md diff --git a/data/changelog/dune-release/2019-05-30-dune-release-1.3.0.md b/data/changelog/releases/dune-release/2019-05-30-dune-release-1.3.0.md similarity index 100% rename from data/changelog/dune-release/2019-05-30-dune-release-1.3.0.md rename to data/changelog/releases/dune-release/2019-05-30-dune-release-1.3.0.md diff --git a/data/changelog/dune-release/2019-06-13-dune-release-1.3.1.md b/data/changelog/releases/dune-release/2019-06-13-dune-release-1.3.1.md similarity index 100% rename from data/changelog/dune-release/2019-06-13-dune-release-1.3.1.md rename to data/changelog/releases/dune-release/2019-06-13-dune-release-1.3.1.md diff --git a/data/changelog/dune-release/2019-07-12-dune-release-1.3.2.md b/data/changelog/releases/dune-release/2019-07-12-dune-release-1.3.2.md similarity index 100% rename from data/changelog/dune-release/2019-07-12-dune-release-1.3.2.md rename to data/changelog/releases/dune-release/2019-07-12-dune-release-1.3.2.md diff --git a/data/changelog/dune-release/2019-09-30-dune-release-1.3.3.md b/data/changelog/releases/dune-release/2019-09-30-dune-release-1.3.3.md similarity index 100% rename from data/changelog/dune-release/2019-09-30-dune-release-1.3.3.md rename to data/changelog/releases/dune-release/2019-09-30-dune-release-1.3.3.md diff --git a/data/changelog/dune-release/2020-07-14-dune-release-1.4.0.md b/data/changelog/releases/dune-release/2020-07-14-dune-release-1.4.0.md similarity index 100% rename from data/changelog/dune-release/2020-07-14-dune-release-1.4.0.md rename to data/changelog/releases/dune-release/2020-07-14-dune-release-1.4.0.md diff --git a/data/changelog/dune-release/2021-07-05-dune-release-1.5.0.md b/data/changelog/releases/dune-release/2021-07-05-dune-release-1.5.0.md similarity index 100% rename from data/changelog/dune-release/2021-07-05-dune-release-1.5.0.md rename to data/changelog/releases/dune-release/2021-07-05-dune-release-1.5.0.md diff --git a/data/changelog/dune-release/2021-10-11-dune-release-1.5.1.md b/data/changelog/releases/dune-release/2021-10-11-dune-release-1.5.1.md similarity index 100% rename from data/changelog/dune-release/2021-10-11-dune-release-1.5.1.md rename to data/changelog/releases/dune-release/2021-10-11-dune-release-1.5.1.md diff --git a/data/changelog/dune-release/2021-11-05-dune-release-1.5.2.md b/data/changelog/releases/dune-release/2021-11-05-dune-release-1.5.2.md similarity index 100% rename from data/changelog/dune-release/2021-11-05-dune-release-1.5.2.md rename to data/changelog/releases/dune-release/2021-11-05-dune-release-1.5.2.md diff --git a/data/changelog/dune-release/2022-02-10-dune-release-1.6.0.md b/data/changelog/releases/dune-release/2022-02-10-dune-release-1.6.0.md similarity index 100% rename from data/changelog/dune-release/2022-02-10-dune-release-1.6.0.md rename to data/changelog/releases/dune-release/2022-02-10-dune-release-1.6.0.md diff --git a/data/changelog/dune-release/2022-02-25-dune-release-1.6.1.md b/data/changelog/releases/dune-release/2022-02-25-dune-release-1.6.1.md similarity index 100% rename from data/changelog/dune-release/2022-02-25-dune-release-1.6.1.md rename to data/changelog/releases/dune-release/2022-02-25-dune-release-1.6.1.md diff --git a/data/changelog/dune-release/2022-05-25-dune-release-1.6.2.md b/data/changelog/releases/dune-release/2022-05-25-dune-release-1.6.2.md similarity index 100% rename from data/changelog/dune-release/2022-05-25-dune-release-1.6.2.md rename to data/changelog/releases/dune-release/2022-05-25-dune-release-1.6.2.md diff --git a/data/changelog/dune-release/2023-06-24-dune-release-2.0.0.md b/data/changelog/releases/dune-release/2023-06-24-dune-release-2.0.0.md similarity index 100% rename from data/changelog/dune-release/2023-06-24-dune-release-2.0.0.md rename to data/changelog/releases/dune-release/2023-06-24-dune-release-2.0.0.md diff --git a/data/changelog/releases/dune-release/2025-02-03-dune-release-2.1.0.md b/data/changelog/releases/dune-release/2025-02-03-dune-release-2.1.0.md new file mode 100644 index 0000000000..8713074c3b --- /dev/null +++ b/data/changelog/releases/dune-release/2025-02-03-dune-release-2.1.0.md @@ -0,0 +1,42 @@ +--- +title: Dune-release 2.1.0 +tags: [dune-release, platform] +changelog: | + ## Added + + - Add `dune-release delegate-info version` to show the current version as infered + by the tool (#495, @samoht) + - Add `--dev-repo` to `dune-release` and `dune-release publish` to overwrite + the `dev-repo` field specified in the opam file (#494, @samoht) + + ### Changed + + - Use the 'user' option as the fork owner, only attempt to decode the remote URL + if the user option is not set. (#480, @Julow) + + ### Fixed + + - Make `dune-release` not fail in the presence of `~/.dune/bin/dune` (which is present + when using dune package management) + + ### Removed + + - `dune-release` no longer publishes docs to github pages. Instead, we rely on + the docs published under `ocaml.org/packages` (#499 #500, @v-gb @samoht) + + +--- + +Dune-release 2.1.0 has been released! + +With this update, +* A new command`dune-release delegate-info version` has been added, which + shows the current version of the package, as inferred by `dune-release`. +* The `dev-repo` field in the `.opam` file can now be overridden using the `--dev-repo` + flag on the commands `dune-release` and `dune-release publish`. +* A bug related to decoding GitHub URLs has been fixed (FIXME:explain context and what's working now that wasn't before) +* `dune-release` no longer publishes docs to github pages. This choice has been made + because, as a consequence of publishing to `opam-repository`, the package + documentation is built and served by `ocaml.org/packages`. +* `dune-release` now works with the experimental package management + feature from Dune Developer Preview. diff --git a/data/changelog/dune/2018-07-11-dune-1.0.0.md b/data/changelog/releases/dune/2018-07-11-dune-1.0.0.md similarity index 100% rename from data/changelog/dune/2018-07-11-dune-1.0.0.md rename to data/changelog/releases/dune/2018-07-11-dune-1.0.0.md diff --git a/data/changelog/dune/2018-07-23-dune-1.0.1.md b/data/changelog/releases/dune/2018-07-23-dune-1.0.1.md similarity index 100% rename from data/changelog/dune/2018-07-23-dune-1.0.1.md rename to data/changelog/releases/dune/2018-07-23-dune-1.0.1.md diff --git a/data/changelog/dune/2018-08-06-dune-1.1.0.md b/data/changelog/releases/dune/2018-08-06-dune-1.1.0.md similarity index 100% rename from data/changelog/dune/2018-08-06-dune-1.1.0.md rename to data/changelog/releases/dune/2018-08-06-dune-1.1.0.md diff --git a/data/changelog/dune/2018-08-09-dune-1.1.1.md b/data/changelog/releases/dune/2018-08-09-dune-1.1.1.md similarity index 100% rename from data/changelog/dune/2018-08-09-dune-1.1.1.md rename to data/changelog/releases/dune/2018-08-09-dune-1.1.1.md diff --git a/data/changelog/dune/2018-09-15-dune-1.2.0.md b/data/changelog/releases/dune/2018-09-15-dune-1.2.0.md similarity index 100% rename from data/changelog/dune/2018-09-15-dune-1.2.0.md rename to data/changelog/releases/dune/2018-09-15-dune-1.2.0.md diff --git a/data/changelog/dune/2018-09-17-dune-1.2.1.md b/data/changelog/releases/dune/2018-09-17-dune-1.2.1.md similarity index 100% rename from data/changelog/dune/2018-09-17-dune-1.2.1.md rename to data/changelog/releases/dune/2018-09-17-dune-1.2.1.md diff --git a/data/changelog/dune/2018-09-25-dune-1.3.0.md b/data/changelog/releases/dune/2018-09-25-dune-1.3.0.md similarity index 100% rename from data/changelog/dune/2018-09-25-dune-1.3.0.md rename to data/changelog/releases/dune/2018-09-25-dune-1.3.0.md diff --git a/data/changelog/dune/2018-10-11-dune-1.4.0.md b/data/changelog/releases/dune/2018-10-11-dune-1.4.0.md similarity index 100% rename from data/changelog/dune/2018-10-11-dune-1.4.0.md rename to data/changelog/releases/dune/2018-10-11-dune-1.4.0.md diff --git a/data/changelog/dune/2018-11-06-dune-1.5.0.md b/data/changelog/releases/dune/2018-11-06-dune-1.5.0.md similarity index 100% rename from data/changelog/dune/2018-11-06-dune-1.5.0.md rename to data/changelog/releases/dune/2018-11-06-dune-1.5.0.md diff --git a/data/changelog/dune/2018-11-07-dune-1.5.1.md b/data/changelog/releases/dune/2018-11-07-dune-1.5.1.md similarity index 100% rename from data/changelog/dune/2018-11-07-dune-1.5.1.md rename to data/changelog/releases/dune/2018-11-07-dune-1.5.1.md diff --git a/data/changelog/dune/2018-12-03-dune-1.6.0.md b/data/changelog/releases/dune/2018-12-03-dune-1.6.0.md similarity index 100% rename from data/changelog/dune/2018-12-03-dune-1.6.0.md rename to data/changelog/releases/dune/2018-12-03-dune-1.6.0.md diff --git a/data/changelog/dune/2018-12-04-dune-1.6.1.md b/data/changelog/releases/dune/2018-12-04-dune-1.6.1.md similarity index 100% rename from data/changelog/dune/2018-12-04-dune-1.6.1.md rename to data/changelog/releases/dune/2018-12-04-dune-1.6.1.md diff --git a/data/changelog/dune/2018-12-05-dune-1.6.2.md b/data/changelog/releases/dune/2018-12-05-dune-1.6.2.md similarity index 100% rename from data/changelog/dune/2018-12-05-dune-1.6.2.md rename to data/changelog/releases/dune/2018-12-05-dune-1.6.2.md diff --git a/data/changelog/dune/2019-01-09-dune-1.6.3.md b/data/changelog/releases/dune/2019-01-09-dune-1.6.3.md similarity index 100% rename from data/changelog/dune/2019-01-09-dune-1.6.3.md rename to data/changelog/releases/dune/2019-01-09-dune-1.6.3.md diff --git a/data/changelog/dune/2019-02-12-dune-1.7.0.md b/data/changelog/releases/dune/2019-02-12-dune-1.7.0.md similarity index 100% rename from data/changelog/dune/2019-02-12-dune-1.7.0.md rename to data/changelog/releases/dune/2019-02-12-dune-1.7.0.md diff --git a/data/changelog/dune/2019-02-13-dune-1.7.1.md b/data/changelog/releases/dune/2019-02-13-dune-1.7.1.md similarity index 100% rename from data/changelog/dune/2019-02-13-dune-1.7.1.md rename to data/changelog/releases/dune/2019-02-13-dune-1.7.1.md diff --git a/data/changelog/dune/2019-02-21-dune-1.7.2.md b/data/changelog/releases/dune/2019-02-21-dune-1.7.2.md similarity index 100% rename from data/changelog/dune/2019-02-21-dune-1.7.2.md rename to data/changelog/releases/dune/2019-02-21-dune-1.7.2.md diff --git a/data/changelog/dune/2019-02-27-dune-1.7.3.md b/data/changelog/releases/dune/2019-02-27-dune-1.7.3.md similarity index 100% rename from data/changelog/dune/2019-02-27-dune-1.7.3.md rename to data/changelog/releases/dune/2019-02-27-dune-1.7.3.md diff --git a/data/changelog/dune/2019-03-07-dune-1.8.0.md b/data/changelog/releases/dune/2019-03-07-dune-1.8.0.md similarity index 100% rename from data/changelog/dune/2019-03-07-dune-1.8.0.md rename to data/changelog/releases/dune/2019-03-07-dune-1.8.0.md diff --git a/data/changelog/dune/2019-03-09-dune-1.8.1.md b/data/changelog/releases/dune/2019-03-09-dune-1.8.1.md similarity index 100% rename from data/changelog/dune/2019-03-09-dune-1.8.1.md rename to data/changelog/releases/dune/2019-03-09-dune-1.8.1.md diff --git a/data/changelog/dune/2019-03-10-dune-1.8.2.md b/data/changelog/releases/dune/2019-03-10-dune-1.8.2.md similarity index 100% rename from data/changelog/dune/2019-03-10-dune-1.8.2.md rename to data/changelog/releases/dune/2019-03-10-dune-1.8.2.md diff --git a/data/changelog/dune/2019-04-09-dune-1.9.0.md b/data/changelog/releases/dune/2019-04-09-dune-1.9.0.md similarity index 100% rename from data/changelog/dune/2019-04-09-dune-1.9.0.md rename to data/changelog/releases/dune/2019-04-09-dune-1.9.0.md diff --git a/data/changelog/dune/2019-04-11-dune-1.9.1.md b/data/changelog/releases/dune/2019-04-11-dune-1.9.1.md similarity index 100% rename from data/changelog/dune/2019-04-11-dune-1.9.1.md rename to data/changelog/releases/dune/2019-04-11-dune-1.9.1.md diff --git a/data/changelog/dune/2019-05-10-dune-1.9.3.md b/data/changelog/releases/dune/2019-05-10-dune-1.9.3.md similarity index 100% rename from data/changelog/dune/2019-05-10-dune-1.9.3.md rename to data/changelog/releases/dune/2019-05-10-dune-1.9.3.md diff --git a/data/changelog/dune/2019-05-11-dune-1.9.2.md b/data/changelog/releases/dune/2019-05-11-dune-1.9.2.md similarity index 100% rename from data/changelog/dune/2019-05-11-dune-1.9.2.md rename to data/changelog/releases/dune/2019-05-11-dune-1.9.2.md diff --git a/data/changelog/dune/2019-06-06-dune-1.10.0.md b/data/changelog/releases/dune/2019-06-06-dune-1.10.0.md similarity index 100% rename from data/changelog/dune/2019-06-06-dune-1.10.0.md rename to data/changelog/releases/dune/2019-06-06-dune-1.10.0.md diff --git a/data/changelog/dune/2019-07-23-dune-1.11.0.md b/data/changelog/releases/dune/2019-07-23-dune-1.11.0.md similarity index 100% rename from data/changelog/dune/2019-07-23-dune-1.11.0.md rename to data/changelog/releases/dune/2019-07-23-dune-1.11.0.md diff --git a/data/changelog/dune/2019-08-11-dune-1.11.1.md b/data/changelog/releases/dune/2019-08-11-dune-1.11.1.md similarity index 100% rename from data/changelog/dune/2019-08-11-dune-1.11.1.md rename to data/changelog/releases/dune/2019-08-11-dune-1.11.1.md diff --git a/data/changelog/dune/2019-08-21-dune-1.11.2.md b/data/changelog/releases/dune/2019-08-21-dune-1.11.2.md similarity index 100% rename from data/changelog/dune/2019-08-21-dune-1.11.2.md rename to data/changelog/releases/dune/2019-08-21-dune-1.11.2.md diff --git a/data/changelog/dune/2019-08-23-dune-1.11.3.md b/data/changelog/releases/dune/2019-08-23-dune-1.11.3.md similarity index 100% rename from data/changelog/dune/2019-08-23-dune-1.11.3.md rename to data/changelog/releases/dune/2019-08-23-dune-1.11.3.md diff --git a/data/changelog/dune/2019-10-09-dune-1.11.4.md b/data/changelog/releases/dune/2019-10-09-dune-1.11.4.md similarity index 100% rename from data/changelog/dune/2019-10-09-dune-1.11.4.md rename to data/changelog/releases/dune/2019-10-09-dune-1.11.4.md diff --git a/data/changelog/dune/2019-11-23-dune-2.0.0.md b/data/changelog/releases/dune/2019-11-23-dune-2.0.0.md similarity index 100% rename from data/changelog/dune/2019-11-23-dune-2.0.0.md rename to data/changelog/releases/dune/2019-11-23-dune-2.0.0.md diff --git a/data/changelog/dune/2019-12-19-dune-2.0.1.md b/data/changelog/releases/dune/2019-12-19-dune-2.0.1.md similarity index 100% rename from data/changelog/dune/2019-12-19-dune-2.0.1.md rename to data/changelog/releases/dune/2019-12-19-dune-2.0.1.md diff --git a/data/changelog/dune/2020-01-07-dune-2.1.1.md b/data/changelog/releases/dune/2020-01-07-dune-2.1.1.md similarity index 100% rename from data/changelog/dune/2020-01-07-dune-2.1.1.md rename to data/changelog/releases/dune/2020-01-07-dune-2.1.1.md diff --git a/data/changelog/dune/2020-01-09-dune-2.1.2.md b/data/changelog/releases/dune/2020-01-09-dune-2.1.2.md similarity index 100% rename from data/changelog/dune/2020-01-09-dune-2.1.2.md rename to data/changelog/releases/dune/2020-01-09-dune-2.1.2.md diff --git a/data/changelog/dune/2020-01-17-dune-2.1.3.md b/data/changelog/releases/dune/2020-01-17-dune-2.1.3.md similarity index 100% rename from data/changelog/dune/2020-01-17-dune-2.1.3.md rename to data/changelog/releases/dune/2020-01-17-dune-2.1.3.md diff --git a/data/changelog/dune/2020-02-09-dune-2.2.0.md b/data/changelog/releases/dune/2020-02-09-dune-2.2.0.md similarity index 100% rename from data/changelog/dune/2020-02-09-dune-2.2.0.md rename to data/changelog/releases/dune/2020-02-09-dune-2.2.0.md diff --git a/data/changelog/dune/2020-02-17-dune-2.3.0.md b/data/changelog/releases/dune/2020-02-17-dune-2.3.0.md similarity index 100% rename from data/changelog/dune/2020-02-17-dune-2.3.0.md rename to data/changelog/releases/dune/2020-02-17-dune-2.3.0.md diff --git a/data/changelog/dune/2020-02-25-dune-2.3.1.md b/data/changelog/releases/dune/2020-02-25-dune-2.3.1.md similarity index 100% rename from data/changelog/dune/2020-02-25-dune-2.3.1.md rename to data/changelog/releases/dune/2020-02-25-dune-2.3.1.md diff --git a/data/changelog/dune/2020-03-09-dune-2.4.0.md b/data/changelog/releases/dune/2020-03-09-dune-2.4.0.md similarity index 100% rename from data/changelog/dune/2020-03-09-dune-2.4.0.md rename to data/changelog/releases/dune/2020-03-09-dune-2.4.0.md diff --git a/data/changelog/dune/2020-04-11-dune-2.5.0.md b/data/changelog/releases/dune/2020-04-11-dune-2.5.0.md similarity index 100% rename from data/changelog/dune/2020-04-11-dune-2.5.0.md rename to data/changelog/releases/dune/2020-04-11-dune-2.5.0.md diff --git a/data/changelog/dune/2020-04-20-dune-2.5.1.md b/data/changelog/releases/dune/2020-04-20-dune-2.5.1.md similarity index 100% rename from data/changelog/dune/2020-04-20-dune-2.5.1.md rename to data/changelog/releases/dune/2020-04-20-dune-2.5.1.md diff --git a/data/changelog/dune/2020-06-09-dune-2.6.0.md b/data/changelog/releases/dune/2020-06-09-dune-2.6.0.md similarity index 100% rename from data/changelog/dune/2020-06-09-dune-2.6.0.md rename to data/changelog/releases/dune/2020-06-09-dune-2.6.0.md diff --git a/data/changelog/dune/2020-07-04-dune-2.6.1.md b/data/changelog/releases/dune/2020-07-04-dune-2.6.1.md similarity index 100% rename from data/changelog/dune/2020-07-04-dune-2.6.1.md rename to data/changelog/releases/dune/2020-07-04-dune-2.6.1.md diff --git a/data/changelog/dune/2020-07-28-dune-2.6.2.md b/data/changelog/releases/dune/2020-07-28-dune-2.6.2.md similarity index 100% rename from data/changelog/dune/2020-07-28-dune-2.6.2.md rename to data/changelog/releases/dune/2020-07-28-dune-2.6.2.md diff --git a/data/changelog/dune/2020-08-18-dune-2.7.0.md b/data/changelog/releases/dune/2020-08-18-dune-2.7.0.md similarity index 100% rename from data/changelog/dune/2020-08-18-dune-2.7.0.md rename to data/changelog/releases/dune/2020-08-18-dune-2.7.0.md diff --git a/data/changelog/dune/2020-09-06-dune-2.7.1.md b/data/changelog/releases/dune/2020-09-06-dune-2.7.1.md similarity index 100% rename from data/changelog/dune/2020-09-06-dune-2.7.1.md rename to data/changelog/releases/dune/2020-09-06-dune-2.7.1.md diff --git a/data/changelog/dune/2021-01-14-dune-2.8.0.md b/data/changelog/releases/dune/2021-01-14-dune-2.8.0.md similarity index 100% rename from data/changelog/dune/2021-01-14-dune-2.8.0.md rename to data/changelog/releases/dune/2021-01-14-dune-2.8.0.md diff --git a/data/changelog/dune/2021-01-14-dune-2.8.1.md b/data/changelog/releases/dune/2021-01-14-dune-2.8.1.md similarity index 100% rename from data/changelog/dune/2021-01-14-dune-2.8.1.md rename to data/changelog/releases/dune/2021-01-14-dune-2.8.1.md diff --git a/data/changelog/dune/2021-01-21-dune-2.8.2.md b/data/changelog/releases/dune/2021-01-21-dune-2.8.2.md similarity index 100% rename from data/changelog/dune/2021-01-21-dune-2.8.2.md rename to data/changelog/releases/dune/2021-01-21-dune-2.8.2.md diff --git a/data/changelog/dune/2021-03-10-dune-2.8.4.md b/data/changelog/releases/dune/2021-03-10-dune-2.8.4.md similarity index 100% rename from data/changelog/dune/2021-03-10-dune-2.8.4.md rename to data/changelog/releases/dune/2021-03-10-dune-2.8.4.md diff --git a/data/changelog/dune/2021-03-30-dune-2.8.5.md b/data/changelog/releases/dune/2021-03-30-dune-2.8.5.md similarity index 100% rename from data/changelog/dune/2021-03-30-dune-2.8.5.md rename to data/changelog/releases/dune/2021-03-30-dune-2.8.5.md diff --git a/data/changelog/dune/2021-07-01-dune-2.9.0.md b/data/changelog/releases/dune/2021-07-01-dune-2.9.0.md similarity index 100% rename from data/changelog/dune/2021-07-01-dune-2.9.0.md rename to data/changelog/releases/dune/2021-07-01-dune-2.9.0.md diff --git a/data/changelog/dune/2021-09-08-dune-2.9.1.md b/data/changelog/releases/dune/2021-09-08-dune-2.9.1.md similarity index 100% rename from data/changelog/dune/2021-09-08-dune-2.9.1.md rename to data/changelog/releases/dune/2021-09-08-dune-2.9.1.md diff --git a/data/changelog/dune/2022-01-23-dune-2.9.2.md b/data/changelog/releases/dune/2022-01-23-dune-2.9.2.md similarity index 100% rename from data/changelog/dune/2022-01-23-dune-2.9.2.md rename to data/changelog/releases/dune/2022-01-23-dune-2.9.2.md diff --git a/data/changelog/dune/2022-01-28-dune-2.9.3.md b/data/changelog/releases/dune/2022-01-28-dune-2.9.3.md similarity index 100% rename from data/changelog/dune/2022-01-28-dune-2.9.3.md rename to data/changelog/releases/dune/2022-01-28-dune-2.9.3.md diff --git a/data/changelog/dune/2022-02-11-dune-3.0.0.md b/data/changelog/releases/dune/2022-02-11-dune-3.0.0.md similarity index 100% rename from data/changelog/dune/2022-02-11-dune-3.0.0.md rename to data/changelog/releases/dune/2022-02-11-dune-3.0.0.md diff --git a/data/changelog/dune/2022-02-19-dune-3.0.2.md b/data/changelog/releases/dune/2022-02-19-dune-3.0.2.md similarity index 100% rename from data/changelog/dune/2022-02-19-dune-3.0.2.md rename to data/changelog/releases/dune/2022-02-19-dune-3.0.2.md diff --git a/data/changelog/dune/2022-03-02-dune-3.0.3.md b/data/changelog/releases/dune/2022-03-02-dune-3.0.3.md similarity index 100% rename from data/changelog/dune/2022-03-02-dune-3.0.3.md rename to data/changelog/releases/dune/2022-03-02-dune-3.0.3.md diff --git a/data/changelog/dune/2022-04-18-dune-3.1.0.md b/data/changelog/releases/dune/2022-04-18-dune-3.1.0.md similarity index 100% rename from data/changelog/dune/2022-04-18-dune-3.1.0.md rename to data/changelog/releases/dune/2022-04-18-dune-3.1.0.md diff --git a/data/changelog/dune/2022-04-20-dune-3.1.1.md b/data/changelog/releases/dune/2022-04-20-dune-3.1.1.md similarity index 100% rename from data/changelog/dune/2022-04-20-dune-3.1.1.md rename to data/changelog/releases/dune/2022-04-20-dune-3.1.1.md diff --git a/data/changelog/dune/2022-05-20-dune-3.2.0.md b/data/changelog/releases/dune/2022-05-20-dune-3.2.0.md similarity index 100% rename from data/changelog/dune/2022-05-20-dune-3.2.0.md rename to data/changelog/releases/dune/2022-05-20-dune-3.2.0.md diff --git a/data/changelog/dune/2022-06-17-dune-3.3.0.md b/data/changelog/releases/dune/2022-06-17-dune-3.3.0.md similarity index 100% rename from data/changelog/dune/2022-06-17-dune-3.3.0.md rename to data/changelog/releases/dune/2022-06-17-dune-3.3.0.md diff --git a/data/changelog/dune/2022-06-21-dune-3.3.1.md b/data/changelog/releases/dune/2022-06-21-dune-3.3.1.md similarity index 100% rename from data/changelog/dune/2022-06-21-dune-3.3.1.md rename to data/changelog/releases/dune/2022-06-21-dune-3.3.1.md diff --git a/data/changelog/dune/2022-07-21-dune-3.4.0.md b/data/changelog/releases/dune/2022-07-21-dune-3.4.0.md similarity index 100% rename from data/changelog/dune/2022-07-21-dune-3.4.0.md rename to data/changelog/releases/dune/2022-07-21-dune-3.4.0.md diff --git a/data/changelog/dune/2022-07-26-dune-3.4.1.md b/data/changelog/releases/dune/2022-07-26-dune-3.4.1.md similarity index 100% rename from data/changelog/dune/2022-07-26-dune-3.4.1.md rename to data/changelog/releases/dune/2022-07-26-dune-3.4.1.md diff --git a/data/changelog/dune/2022-10-20-dune-3.5.0.md b/data/changelog/releases/dune/2022-10-20-dune-3.5.0.md similarity index 100% rename from data/changelog/dune/2022-10-20-dune-3.5.0.md rename to data/changelog/releases/dune/2022-10-20-dune-3.5.0.md diff --git a/data/changelog/dune/2022-11-17-dune-3.6.0.md b/data/changelog/releases/dune/2022-11-17-dune-3.6.0.md similarity index 100% rename from data/changelog/dune/2022-11-17-dune-3.6.0.md rename to data/changelog/releases/dune/2022-11-17-dune-3.6.0.md diff --git a/data/changelog/dune/2022-11-24-dune-3.6.1.md b/data/changelog/releases/dune/2022-11-24-dune-3.6.1.md similarity index 100% rename from data/changelog/dune/2022-11-24-dune-3.6.1.md rename to data/changelog/releases/dune/2022-11-24-dune-3.6.1.md diff --git a/data/changelog/dune/2023-02-07-dune-3.6.2.md b/data/changelog/releases/dune/2023-02-07-dune-3.6.2.md similarity index 100% rename from data/changelog/dune/2023-02-07-dune-3.6.2.md rename to data/changelog/releases/dune/2023-02-07-dune-3.6.2.md diff --git a/data/changelog/dune/2023-02-20-dune-3.7.0.md b/data/changelog/releases/dune/2023-02-20-dune-3.7.0.md similarity index 100% rename from data/changelog/dune/2023-02-20-dune-3.7.0.md rename to data/changelog/releases/dune/2023-02-20-dune-3.7.0.md diff --git a/data/changelog/dune/2023-04-05-dune-3.7.1.md b/data/changelog/releases/dune/2023-04-05-dune-3.7.1.md similarity index 100% rename from data/changelog/dune/2023-04-05-dune-3.7.1.md rename to data/changelog/releases/dune/2023-04-05-dune-3.7.1.md diff --git a/data/changelog/dune/2023-05-31-dune-3.8.0.md b/data/changelog/releases/dune/2023-05-31-dune-3.8.0.md similarity index 100% rename from data/changelog/dune/2023-05-31-dune-3.8.0.md rename to data/changelog/releases/dune/2023-05-31-dune-3.8.0.md diff --git a/data/changelog/dune/2023-06-06-dune-3.8.1.md b/data/changelog/releases/dune/2023-06-06-dune-3.8.1.md similarity index 100% rename from data/changelog/dune/2023-06-06-dune-3.8.1.md rename to data/changelog/releases/dune/2023-06-06-dune-3.8.1.md diff --git a/data/changelog/dune/2023-06-19-dune-3.8.2.md b/data/changelog/releases/dune/2023-06-19-dune-3.8.2.md similarity index 100% rename from data/changelog/dune/2023-06-19-dune-3.8.2.md rename to data/changelog/releases/dune/2023-06-19-dune-3.8.2.md diff --git a/data/changelog/dune/2023-06-28-dune-3.8.3.md b/data/changelog/releases/dune/2023-06-28-dune-3.8.3.md similarity index 100% rename from data/changelog/dune/2023-06-28-dune-3.8.3.md rename to data/changelog/releases/dune/2023-06-28-dune-3.8.3.md diff --git a/data/changelog/dune/2023-06-30-dune-3.9.0.md b/data/changelog/releases/dune/2023-06-30-dune-3.9.0.md similarity index 100% rename from data/changelog/dune/2023-06-30-dune-3.9.0.md rename to data/changelog/releases/dune/2023-06-30-dune-3.9.0.md diff --git a/data/changelog/dune/2023-07-06-dune-3.9.1.md b/data/changelog/releases/dune/2023-07-06-dune-3.9.1.md similarity index 100% rename from data/changelog/dune/2023-07-06-dune-3.9.1.md rename to data/changelog/releases/dune/2023-07-06-dune-3.9.1.md diff --git a/data/changelog/dune/2023-07-25-dune-3.9.2.md b/data/changelog/releases/dune/2023-07-25-dune-3.9.2.md similarity index 100% rename from data/changelog/dune/2023-07-25-dune-3.9.2.md rename to data/changelog/releases/dune/2023-07-25-dune-3.9.2.md diff --git a/data/changelog/dune/2023-07-31-dune-3.10.0.md b/data/changelog/releases/dune/2023-07-31-dune-3.10.0.md similarity index 100% rename from data/changelog/dune/2023-07-31-dune-3.10.0.md rename to data/changelog/releases/dune/2023-07-31-dune-3.10.0.md diff --git a/data/changelog/dune/2023-07-31-dune-3.9.3.md b/data/changelog/releases/dune/2023-07-31-dune-3.9.3.md similarity index 100% rename from data/changelog/dune/2023-07-31-dune-3.9.3.md rename to data/changelog/releases/dune/2023-07-31-dune-3.9.3.md diff --git a/data/changelog/dune/2023-10-04-dune-3.11.0.md b/data/changelog/releases/dune/2023-10-04-dune-3.11.0.md similarity index 100% rename from data/changelog/dune/2023-10-04-dune-3.11.0.md rename to data/changelog/releases/dune/2023-10-04-dune-3.11.0.md diff --git a/data/changelog/dune/2023-10-12-dune-3.11.1.md b/data/changelog/releases/dune/2023-10-12-dune-3.11.1.md similarity index 100% rename from data/changelog/dune/2023-10-12-dune-3.11.1.md rename to data/changelog/releases/dune/2023-10-12-dune-3.11.1.md diff --git a/data/changelog/dune/2023-11-29-dune-3.12.1.md b/data/changelog/releases/dune/2023-11-29-dune-3.12.1.md similarity index 100% rename from data/changelog/dune/2023-11-29-dune-3.12.1.md rename to data/changelog/releases/dune/2023-11-29-dune-3.12.1.md diff --git a/data/changelog/dune/2024-01-05-dune-3.12.2.md b/data/changelog/releases/dune/2024-01-05-dune-3.12.2.md similarity index 100% rename from data/changelog/dune/2024-01-05-dune-3.12.2.md rename to data/changelog/releases/dune/2024-01-05-dune-3.12.2.md diff --git a/data/changelog/dune/2024-01-16-dune-3.13.0.md b/data/changelog/releases/dune/2024-01-16-dune-3.13.0.md similarity index 100% rename from data/changelog/dune/2024-01-16-dune-3.13.0.md rename to data/changelog/releases/dune/2024-01-16-dune-3.13.0.md diff --git a/data/changelog/dune/2024-02-05-dune-3.13.1.md b/data/changelog/releases/dune/2024-02-05-dune-3.13.1.md similarity index 100% rename from data/changelog/dune/2024-02-05-dune-3.13.1.md rename to data/changelog/releases/dune/2024-02-05-dune-3.13.1.md diff --git a/data/changelog/dune/2024-02-12-dune.3.14.0.md b/data/changelog/releases/dune/2024-02-12-dune.3.14.0.md similarity index 100% rename from data/changelog/dune/2024-02-12-dune.3.14.0.md rename to data/changelog/releases/dune/2024-02-12-dune.3.14.0.md diff --git a/data/changelog/dune/2024-03-13-dune.3.14.2.md b/data/changelog/releases/dune/2024-03-13-dune.3.14.2.md similarity index 100% rename from data/changelog/dune/2024-03-13-dune.3.14.2.md rename to data/changelog/releases/dune/2024-03-13-dune.3.14.2.md diff --git a/data/changelog/dune/2024-04-03-dune.3.15.0.md b/data/changelog/releases/dune/2024-04-03-dune.3.15.0.md similarity index 100% rename from data/changelog/dune/2024-04-03-dune.3.15.0.md rename to data/changelog/releases/dune/2024-04-03-dune.3.15.0.md diff --git a/data/changelog/dune/2024-04-23-dune.3.15.2.md b/data/changelog/releases/dune/2024-04-23-dune.3.15.2.md similarity index 100% rename from data/changelog/dune/2024-04-23-dune.3.15.2.md rename to data/changelog/releases/dune/2024-04-23-dune.3.15.2.md diff --git a/data/changelog/dune/2024-05-26-dune.3.15.3.md b/data/changelog/releases/dune/2024-05-26-dune.3.15.3.md similarity index 100% rename from data/changelog/dune/2024-05-26-dune.3.15.3.md rename to data/changelog/releases/dune/2024-05-26-dune.3.15.3.md diff --git a/data/changelog/dune/2024-06-17-dune.3.16.0.md b/data/changelog/releases/dune/2024-06-17-dune.3.16.0.md similarity index 100% rename from data/changelog/dune/2024-06-17-dune.3.16.0.md rename to data/changelog/releases/dune/2024-06-17-dune.3.16.0.md diff --git a/data/changelog/dune/2024-10-30-dune.3.16.1.md b/data/changelog/releases/dune/2024-10-30-dune.3.16.1.md similarity index 100% rename from data/changelog/dune/2024-10-30-dune.3.16.1.md rename to data/changelog/releases/dune/2024-10-30-dune.3.16.1.md diff --git a/data/changelog/dune/2024-11-27-dune.3.17.0.md b/data/changelog/releases/dune/2024-11-27-dune.3.17.0.md similarity index 100% rename from data/changelog/dune/2024-11-27-dune.3.17.0.md rename to data/changelog/releases/dune/2024-11-27-dune.3.17.0.md diff --git a/data/changelog/dune/2024-12-18-dune.3.17.1.md b/data/changelog/releases/dune/2024-12-18-dune.3.17.1.md similarity index 100% rename from data/changelog/dune/2024-12-18-dune.3.17.1.md rename to data/changelog/releases/dune/2024-12-18-dune.3.17.1.md diff --git a/data/changelog/releases/dune/2025-01-23-dune.3.17.2.md b/data/changelog/releases/dune/2025-01-23-dune.3.17.2.md new file mode 100644 index 0000000000..02c43b9beb --- /dev/null +++ b/data/changelog/releases/dune/2025-01-23-dune.3.17.2.md @@ -0,0 +1,20 @@ +--- +title: Dune 3.17.2 +tags: [dune, platform] +changelog: | + ### Fixed + + - Fix a crash in the Melange rules that would prevent compiling public library + implementations of virtual libraries. (@anmonteiro, #11248) + - Pass `melange.emit`'s `compile_flags` to the JS emission phase. (@anmonteiro, + #11252) + - Disallow private implementations of public virtual libs in melange mode. + (@anmonteiro, #11253) + - Wasm_of_ocaml: fix the execution of tests in a sandbox. (#11304, @vouillon) +--- + +The Dune team is happy to announce the release of Dune 3.17.2! + +This patch release includes some bug fixes. It brings some fixes for Melange +and Wasm_of_ocaml. It also fixes a bug that prevents the experimental feature, +package management, to build with `ocaml.5.3.0`. diff --git a/data/changelog/releases/dune/2025-04-03-dune.3.18.0.md b/data/changelog/releases/dune/2025-04-03-dune.3.18.0.md new file mode 100644 index 0000000000..3f6c686dd5 --- /dev/null +++ b/data/changelog/releases/dune/2025-04-03-dune.3.18.0.md @@ -0,0 +1,60 @@ +--- +title: Dune 3.18.0 +tags: [dune, platform] +changelog: | + ### Fixed + + - Support HaikuOS: don't call `execve` since it's not allowed if other pthreads + have been created. The fact that Haiku can't call `execve` from other threads + than the principal thread of a process (a team in haiku jargon), is a + discrepancy to POSIX and hence there is a [bug about + it](https://dev.haiku-os.org/ticket/18665). (@Sylvain78, #10953) + + - Fix flag ordering in generated Merlin configurations (#11503, @voodoos, fixes + ocaml/merlin#1900, reported by @vouillon) + + ### Added + + - Add `(format-dune-file )` action. It provides a replacement to + `dune format-dune-file` command. (#11166, @nojb) + + - Allow the `--prefix` flag when configuring dune with `ocaml configure.ml`. + This allows to set the prefix just like `$ dune install --prefix`. (#11172, + @rgrinberg) + + - Allow arguments starting with `+` in preprocessing definitions (starting with + `(lang dune 3.18)`). (@amonteiro, #11234) + + - Support for opam `(maintenance_intent ...)` in dune-project (#11274, @art-w) + + - Validate opam `maintenance_intent` (#11308, @art-w) + + - Support `not` in package dependencies constraints (#11404, @art-w, reported + by @hannesm) + + ### Changed + + - Warn when failing to discover root due to reads failing. The previous + behavior was to abort. (@KoviRobi, #11173) + + - Use shorter path for inline-tests artifacts. (@hhugo, #11307) + + - Allow dash in `dune init` project name (#11402, @art-w, reported by @saroupille) + + - On Windows, under heavy load, file delete operations can sometimes fail due to + AV programs, etc. Guard against it by retrying the operation up to 30x with a + 1s waiting gap (#11437, fixes #11425, @MSoegtropIMC) + + - Cache: we now only store the executable permission bit for files (#11541, + fixes #11533, @ElectreAAS) + + - Display negative error codes on Windows in hex which is the more customary + way to display `NTSTATUS` codes (#11504, @MisterDA) +--- +The Dune Team is happy to announce the release of Dune `3.18.0`! + +This release contains changes to support the new `x-maintenance-intent` field +by default. It also contains some changes regarding the cache about how it +handles file permissions. It introduces a new `(format-dune-file ...)` stanza +with the intention to formalize the `dune format-dune-file` command as an inside +rule. Finally, it includes various bug fixes for Dune. diff --git a/data/changelog/releases/dune/2025-04-17-dune.3.18.1.md b/data/changelog/releases/dune/2025-04-17-dune.3.18.1.md new file mode 100644 index 0000000000..cba0ca97bc --- /dev/null +++ b/data/changelog/releases/dune/2025-04-17-dune.3.18.1.md @@ -0,0 +1,15 @@ +--- +title: Dune.3.18.1 +tags: [dune, platform] +changelog: | + ### Fixed + + - fix: pass pkg-config (extra) args in all pkgconfig invocations. A missing + `--personality` flag would result in pkgconf not finding libraries in some + contexts. (#11619, @MisterDA) +--- + +The Dune Team is happy to announce the release of Dune `3.18.1`! + +This release contains a bug fix for `pkg-config` that prevents it from finding some +libraries in specific contexts. diff --git a/data/changelog/releases/dune/2025-04-30-dune.3.18.2.md b/data/changelog/releases/dune/2025-04-30-dune.3.18.2.md new file mode 100644 index 0000000000..57a63badf9 --- /dev/null +++ b/data/changelog/releases/dune/2025-04-30-dune.3.18.2.md @@ -0,0 +1,13 @@ +--- +title: Dune.3.18.2 +tags: [dune, platform] +changelog: | + ### Fixed + + - fix compatibility with `ocaml.5.4.0` by avoiding shadowing sigwinch (@nojb, + #11639) +--- + +The Dune Team is happy to announce the release of Dune `3.18.2`. + +This release contains a bug fix to fix a compatibility issue with `ocaml.5.4.0`. diff --git a/data/changelog/infra/2022-11-04-relocating-ocaml-org.md b/data/changelog/releases/infra/2022-11-04-relocating-ocaml-org.md similarity index 83% rename from data/changelog/infra/2022-11-04-relocating-ocaml-org.md rename to data/changelog/releases/infra/2022-11-04-relocating-ocaml-org.md index 73ed71317b..0cbd76bf0e 100644 --- a/data/changelog/infra/2022-11-04-relocating-ocaml-org.md +++ b/data/changelog/releases/infra/2022-11-04-relocating-ocaml-org.md @@ -1,5 +1,5 @@ --- -title: Relocating OCaml.org +title: "OCaml Infrastructure: Relocating OCaml.org" tags: [infrastructure] --- diff --git a/data/changelog/infra/2022-11-08-tarsnap-backups.md b/data/changelog/releases/infra/2022-11-08-tarsnap-backups.md similarity index 92% rename from data/changelog/infra/2022-11-08-tarsnap-backups.md rename to data/changelog/releases/infra/2022-11-08-tarsnap-backups.md index c14a2696e3..38f14c0baa 100644 --- a/data/changelog/infra/2022-11-08-tarsnap-backups.md +++ b/data/changelog/releases/infra/2022-11-08-tarsnap-backups.md @@ -1,5 +1,5 @@ --- -title: Now using Tarsnap for VM backups +title: "OCaml Infrastructure: Now using Tarsnap for VM Backups" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-02-27-watch-ocaml-org.md b/data/changelog/releases/infra/2023-02-27-watch-ocaml-org.md similarity index 96% rename from data/changelog/infra/2023-02-27-watch-ocaml-org.md rename to data/changelog/releases/infra/2023-02-27-watch-ocaml-org.md index aeff0c401e..c4077d3a94 100644 --- a/data/changelog/infra/2023-02-27-watch-ocaml-org.md +++ b/data/changelog/releases/infra/2023-02-27-watch-ocaml-org.md @@ -1,5 +1,5 @@ --- -title: Promote watch.ocaml.org to non-beta +title: "OCaml Infrastructure: Promote watch.ocaml.org to Non-Beta Status" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-03-09-moving-opam-ocaml-org.md b/data/changelog/releases/infra/2023-03-09-moving-opam-ocaml-org.md similarity index 95% rename from data/changelog/infra/2023-03-09-moving-opam-ocaml-org.md rename to data/changelog/releases/infra/2023-03-09-moving-opam-ocaml-org.md index 1eb8a13374..a5d20110e2 100644 --- a/data/changelog/infra/2023-03-09-moving-opam-ocaml-org.md +++ b/data/changelog/releases/infra/2023-03-09-moving-opam-ocaml-org.md @@ -1,5 +1,5 @@ --- -title: opam.ocaml.org move to Scaleway +title: "OCaml Infrastructure: opam.ocaml.org Moves to Scaleway" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-03-10-opam-repository-mingw.md b/data/changelog/releases/infra/2023-03-10-opam-repository-mingw.md similarity index 99% rename from data/changelog/infra/2023-03-10-opam-repository-mingw.md rename to data/changelog/releases/infra/2023-03-10-opam-repository-mingw.md index e4502b58fc..8e8996cd0e 100644 --- a/data/changelog/infra/2023-03-10-opam-repository-mingw.md +++ b/data/changelog/releases/infra/2023-03-10-opam-repository-mingw.md @@ -1,5 +1,5 @@ --- -title: Sunsetting opam-repository-mingw +title: "OCaml Infrastructure: Sunsetting opam-repository-mingw" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-03-17-opam-ci-ocaml-org.md b/data/changelog/releases/infra/2023-03-17-opam-ci-ocaml-org.md similarity index 91% rename from data/changelog/infra/2023-03-17-opam-ci-ocaml-org.md rename to data/changelog/releases/infra/2023-03-17-opam-ci-ocaml-org.md index f0d30d3bc9..fc3a3f469d 100644 --- a/data/changelog/infra/2023-03-17-opam-ci-ocaml-org.md +++ b/data/changelog/releases/infra/2023-03-17-opam-ci-ocaml-org.md @@ -1,5 +1,5 @@ --- -title: Renaming opam.ci.ocaml.org / opam.ci3.ocamllabs.io +title: "OCaml Infrastructure: Renaming opam.ci.ocaml.org / opam.ci3.ocamllabs.io" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-04-06-maintenance-operations.md b/data/changelog/releases/infra/2023-04-06-maintenance-operations.md similarity index 85% rename from data/changelog/infra/2023-04-06-maintenance-operations.md rename to data/changelog/releases/infra/2023-04-06-maintenance-operations.md index eab51d9260..98acbb7b60 100644 --- a/data/changelog/infra/2023-04-06-maintenance-operations.md +++ b/data/changelog/releases/infra/2023-04-06-maintenance-operations.md @@ -1,5 +1,5 @@ --- -title: Maintenance Operations +title: "OCaml Infrastructure: Maintenance Operations" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-04-25-updated-images.md b/data/changelog/releases/infra/2023-04-25-updated-images.md similarity index 93% rename from data/changelog/infra/2023-04-25-updated-images.md rename to data/changelog/releases/infra/2023-04-25-updated-images.md index 7c99e85452..ef43a7ee0d 100644 --- a/data/changelog/infra/2023-04-25-updated-images.md +++ b/data/changelog/releases/infra/2023-04-25-updated-images.md @@ -1,5 +1,5 @@ --- -title: Updated Linux Distros and OCaml versions +title: "OCaml Infrastructure: Updated Linux Distros and OCaml versions" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-04-26-check-ci-ocaml-org.md b/data/changelog/releases/infra/2023-04-26-check-ci-ocaml-org.md similarity index 77% rename from data/changelog/infra/2023-04-26-check-ci-ocaml-org.md rename to data/changelog/releases/infra/2023-04-26-check-ci-ocaml-org.md index 6becd3e09b..67fce4dc90 100644 --- a/data/changelog/infra/2023-04-26-check-ci-ocaml-org.md +++ b/data/changelog/releases/infra/2023-04-26-check-ci-ocaml-org.md @@ -1,5 +1,5 @@ --- -title: check.ocamllabs.io moved to check.ci.ocaml.org +title: "OCaml Infrastructure: check.ocamllabs.io moved to check.ci.ocaml.org" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-05-05-opam-repo-ci.md b/data/changelog/releases/infra/2023-05-05-opam-repo-ci.md similarity index 83% rename from data/changelog/infra/2023-05-05-opam-repo-ci.md rename to data/changelog/releases/infra/2023-05-05-opam-repo-ci.md index 3e2c893f52..4d6e07213d 100644 --- a/data/changelog/infra/2023-05-05-opam-repo-ci.md +++ b/data/changelog/releases/infra/2023-05-05-opam-repo-ci.md @@ -1,5 +1,5 @@ --- -title: Temporary relocation of opam.ci.ocaml.org +title: "OCaml Infrastructure: Temporary relocation of opam.ci.ocaml.org" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-06-09-grafana-changes.md b/data/changelog/releases/infra/2023-06-09-grafana-changes.md similarity index 82% rename from data/changelog/infra/2023-06-09-grafana-changes.md rename to data/changelog/releases/infra/2023-06-09-grafana-changes.md index ae50bc3e57..c7f6a8aaad 100644 --- a/data/changelog/infra/2023-06-09-grafana-changes.md +++ b/data/changelog/releases/infra/2023-06-09-grafana-changes.md @@ -1,5 +1,5 @@ --- -title: Grafana Dashboard Changes +title: "OCaml Infrastructure: Grafana Dashboard Changes" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-06-15-opam-repo-ci-ocaml-ci.md b/data/changelog/releases/infra/2023-06-15-opam-repo-ci-ocaml-ci.md similarity index 89% rename from data/changelog/infra/2023-06-15-opam-repo-ci-ocaml-ci.md rename to data/changelog/releases/infra/2023-06-15-opam-repo-ci-ocaml-ci.md index 754764ffc9..f0aaa2cbe6 100644 --- a/data/changelog/infra/2023-06-15-opam-repo-ci-ocaml-ci.md +++ b/data/changelog/releases/infra/2023-06-15-opam-repo-ci-ocaml-ci.md @@ -1,5 +1,5 @@ --- -title: Relocation of opam.ci.ocaml.org and ocaml.ci.dev +title: "OCaml Infrastructure: Relocation of opam.ci.ocaml.org and ocaml.ci.dev" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-06-28-upgrading-linux-distros.md b/data/changelog/releases/infra/2023-06-28-upgrading-linux-distros.md similarity index 94% rename from data/changelog/infra/2023-06-28-upgrading-linux-distros.md rename to data/changelog/releases/infra/2023-06-28-upgrading-linux-distros.md index 60bf675aa8..1ac955e9fd 100644 --- a/data/changelog/infra/2023-06-28-upgrading-linux-distros.md +++ b/data/changelog/releases/infra/2023-06-28-upgrading-linux-distros.md @@ -1,5 +1,5 @@ --- -title: OCaml infra upgrading to Debian 12 for OCaml docker images +title: "OCaml Infrastructure: Upgrading to Debian 12 for OCaml docker images" tags: [infrastructure] changelog: | * OCaml Debian images upgraded to Debian 12 ([ocaml-dockerfile#172](https://github.com/ocurrent/ocaml-dockerfile/pull/172/files), @MisterDA) diff --git a/data/changelog/infra/2023-08-08-freebsd-testing.md b/data/changelog/releases/infra/2023-08-08-freebsd-testing.md similarity index 82% rename from data/changelog/infra/2023-08-08-freebsd-testing.md rename to data/changelog/releases/infra/2023-08-08-freebsd-testing.md index 4bcc6312ba..feffaf70ea 100644 --- a/data/changelog/infra/2023-08-08-freebsd-testing.md +++ b/data/changelog/releases/infra/2023-08-08-freebsd-testing.md @@ -1,5 +1,5 @@ --- -title: FreeBSD is now tested in opam-repo-ci +title: "OCaml Infrastructure: FreeBSD is Now Tested in opam-repo-ci" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-09-21-more-freebsd-news.md b/data/changelog/releases/infra/2023-09-21-more-freebsd-news.md similarity index 92% rename from data/changelog/infra/2023-09-21-more-freebsd-news.md rename to data/changelog/releases/infra/2023-09-21-more-freebsd-news.md index dfd0dee3bb..ab84d5013e 100644 --- a/data/changelog/infra/2023-09-21-more-freebsd-news.md +++ b/data/changelog/releases/infra/2023-09-21-more-freebsd-news.md @@ -1,5 +1,5 @@ --- -title: FreeBSD is Available in More Places +title: "OCaml Infrastructure: FreeBSD Available in More Parts of the Infrastructure " tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-11-09-macos-sonoma.md b/data/changelog/releases/infra/2023-11-09-macos-sonoma.md similarity index 87% rename from data/changelog/infra/2023-11-09-macos-sonoma.md rename to data/changelog/releases/infra/2023-11-09-macos-sonoma.md index c608d75931..88cdc60e3b 100644 --- a/data/changelog/infra/2023-11-09-macos-sonoma.md +++ b/data/changelog/releases/infra/2023-11-09-macos-sonoma.md @@ -1,5 +1,5 @@ --- -title: macOS Sonoma Update +title: "OCaml Infrastructure: macOS Sonoma Update" tags: [infrastructure] --- diff --git a/data/changelog/infra/2023-12-04-relocate-services.md b/data/changelog/releases/infra/2023-12-04-relocate-services.md similarity index 95% rename from data/changelog/infra/2023-12-04-relocate-services.md rename to data/changelog/releases/infra/2023-12-04-relocate-services.md index e1036db91a..e905c69434 100644 --- a/data/changelog/infra/2023-12-04-relocate-services.md +++ b/data/changelog/releases/infra/2023-12-04-relocate-services.md @@ -1,5 +1,5 @@ --- -title: Relocating opam.ci.ocaml.org and ocaml.ci.dev +title: "OCaml Infrastructure: Relocating opam.ci.ocaml.org and ocaml.ci.dev" tags: [infrastructure] --- diff --git a/data/changelog/infra/2024-10-02-updates.md b/data/changelog/releases/infra/2024-10-02-updates.md similarity index 100% rename from data/changelog/infra/2024-10-02-updates.md rename to data/changelog/releases/infra/2024-10-02-updates.md diff --git a/data/changelog/releases/infra/2025-03-24-recent-ocaml-versions.md b/data/changelog/releases/infra/2025-03-24-recent-ocaml-versions.md new file mode 100644 index 0000000000..4a95519448 --- /dev/null +++ b/data/changelog/releases/infra/2025-03-24-recent-ocaml-versions.md @@ -0,0 +1,14 @@ +--- +title: "OCaml Infrastructure: OCaml-version 4.0.0 released" +tags: [infrastructure] +changelog: | + - ocaml-version 4.0.0 released (by ~mtelvers, https://github.com/ocurrent/ocaml/version) +--- + +Following a post on [discuss.ocaml.org](https://discuss.ocaml.org/t/docker-base-images-and-ocaml-ci-support-for-ocaml-4-08/16229), there has been a new release of [ocurrent/ocaml-version](https://github.com/ocurrent/ocaml-version) that moves the minimum version of OCaml, considered as _recent_, from 4.02 to 4.08. + +```ocaml +let recent = [ v4_08; v4_09; v4_10; v4_11; v4_12; v4_13; v4_14; v5_0; v5_1; v5_2; v5_3 ] +``` + +This change has far reaching side effects as [OCaml-CI](https://github.com/ocurrent/ocaml-ci), [opam-repo-ci](https://github.com/ocurrent/opam-repo-ci), [Docker base image builder](https://github.com/ocurrent/docker-base-images) among other things, use this to determine the set of versions of OCaml to test against. As these services are updated, testing on the old releases will be removed. diff --git a/data/changelog/releases/infra/2025-03-26-freebsd-14.2.md b/data/changelog/releases/infra/2025-03-26-freebsd-14.2.md new file mode 100644 index 0000000000..5b1a663fd2 --- /dev/null +++ b/data/changelog/releases/infra/2025-03-26-freebsd-14.2.md @@ -0,0 +1,8 @@ +--- +title: "OCaml Infrastructure: FreeBSD 14.2 Upgrade" +tags: [infrastructure] +--- + +[OBuilder](https://github.com/ocurrent/obuilder) workers for FreeBSD have been updated to FreeBSD 14.2. See [ocurrent/freebsd-infra](https://github.com/ocurrent/freebsd-infra/commit/e9062f1b5a89bce9b26a1f79d09e88b5477a7f65) + +From today, [ocaml-ci](https://ocaml.ci.dev) and [opam-repo-ci](https://opam.ci.ocaml.org) will test against FreeBSD 14.2 rather than 14.1. diff --git a/data/changelog/mdx/2018-09-24-mdx-1.0.0.md b/data/changelog/releases/mdx/2018-09-24-mdx-1.0.0.md similarity index 100% rename from data/changelog/mdx/2018-09-24-mdx-1.0.0.md rename to data/changelog/releases/mdx/2018-09-24-mdx-1.0.0.md diff --git a/data/changelog/mdx/2019-01-10-mdx-1.2.0.md b/data/changelog/releases/mdx/2019-01-10-mdx-1.2.0.md similarity index 100% rename from data/changelog/mdx/2019-01-10-mdx-1.2.0.md rename to data/changelog/releases/mdx/2019-01-10-mdx-1.2.0.md diff --git a/data/changelog/mdx/2019-03-04-mdx-1.3.0.md b/data/changelog/releases/mdx/2019-03-04-mdx-1.3.0.md similarity index 100% rename from data/changelog/mdx/2019-03-04-mdx-1.3.0.md rename to data/changelog/releases/mdx/2019-03-04-mdx-1.3.0.md diff --git a/data/changelog/mdx/2019-06-15-mdx-1.4.0.md b/data/changelog/releases/mdx/2019-06-15-mdx-1.4.0.md similarity index 100% rename from data/changelog/mdx/2019-06-15-mdx-1.4.0.md rename to data/changelog/releases/mdx/2019-06-15-mdx-1.4.0.md diff --git a/data/changelog/mdx/2019-12-02-mdx-1.5.0.md b/data/changelog/releases/mdx/2019-12-02-mdx-1.5.0.md similarity index 100% rename from data/changelog/mdx/2019-12-02-mdx-1.5.0.md rename to data/changelog/releases/mdx/2019-12-02-mdx-1.5.0.md diff --git a/data/changelog/mdx/2020-02-19-mdx-1.6.0.md b/data/changelog/releases/mdx/2020-02-19-mdx-1.6.0.md similarity index 100% rename from data/changelog/mdx/2020-02-19-mdx-1.6.0.md rename to data/changelog/releases/mdx/2020-02-19-mdx-1.6.0.md diff --git a/data/changelog/mdx/2020-07-21-mdx-1.7.0.md b/data/changelog/releases/mdx/2020-07-21-mdx-1.7.0.md similarity index 100% rename from data/changelog/mdx/2020-07-21-mdx-1.7.0.md rename to data/changelog/releases/mdx/2020-07-21-mdx-1.7.0.md diff --git a/data/changelog/mdx/2021-01-18-mdx-1.8.0.md b/data/changelog/releases/mdx/2021-01-18-mdx-1.8.0.md similarity index 100% rename from data/changelog/mdx/2021-01-18-mdx-1.8.0.md rename to data/changelog/releases/mdx/2021-01-18-mdx-1.8.0.md diff --git a/data/changelog/mdx/2021-02-12-mdx-1.8.1.md b/data/changelog/releases/mdx/2021-02-12-mdx-1.8.1.md similarity index 100% rename from data/changelog/mdx/2021-02-12-mdx-1.8.1.md rename to data/changelog/releases/mdx/2021-02-12-mdx-1.8.1.md diff --git a/data/changelog/mdx/2021-06-04-mdx-1.9.0.md b/data/changelog/releases/mdx/2021-06-04-mdx-1.9.0.md similarity index 100% rename from data/changelog/mdx/2021-06-04-mdx-1.9.0.md rename to data/changelog/releases/mdx/2021-06-04-mdx-1.9.0.md diff --git a/data/changelog/mdx/2021-07-05-mdx-1.10.0.md b/data/changelog/releases/mdx/2021-07-05-mdx-1.10.0.md similarity index 100% rename from data/changelog/mdx/2021-07-05-mdx-1.10.0.md rename to data/changelog/releases/mdx/2021-07-05-mdx-1.10.0.md diff --git a/data/changelog/mdx/2021-07-12-mdx-1.10.1.md b/data/changelog/releases/mdx/2021-07-12-mdx-1.10.1.md similarity index 100% rename from data/changelog/mdx/2021-07-12-mdx-1.10.1.md rename to data/changelog/releases/mdx/2021-07-12-mdx-1.10.1.md diff --git a/data/changelog/mdx/2021-09-09-mdx-1.11.0.md b/data/changelog/releases/mdx/2021-09-09-mdx-1.11.0.md similarity index 100% rename from data/changelog/mdx/2021-09-09-mdx-1.11.0.md rename to data/changelog/releases/mdx/2021-09-09-mdx-1.11.0.md diff --git a/data/changelog/mdx/2021-12-09-mdx-1.11.1.md b/data/changelog/releases/mdx/2021-12-09-mdx-1.11.1.md similarity index 100% rename from data/changelog/mdx/2021-12-09-mdx-1.11.1.md rename to data/changelog/releases/mdx/2021-12-09-mdx-1.11.1.md diff --git a/data/changelog/mdx/2021-12-15-mdx-2.0.0.md b/data/changelog/releases/mdx/2021-12-15-mdx-2.0.0.md similarity index 100% rename from data/changelog/mdx/2021-12-15-mdx-2.0.0.md rename to data/changelog/releases/mdx/2021-12-15-mdx-2.0.0.md diff --git a/data/changelog/mdx/2022-01-28-mdx-2.1.0.md b/data/changelog/releases/mdx/2022-01-28-mdx-2.1.0.md similarity index 100% rename from data/changelog/mdx/2022-01-28-mdx-2.1.0.md rename to data/changelog/releases/mdx/2022-01-28-mdx-2.1.0.md diff --git a/data/changelog/mdx/2023-01-12-mdx-2.2.0.md b/data/changelog/releases/mdx/2023-01-12-mdx-2.2.0.md similarity index 100% rename from data/changelog/mdx/2023-01-12-mdx-2.2.0.md rename to data/changelog/releases/mdx/2023-01-12-mdx-2.2.0.md diff --git a/data/changelog/mdx/2023-01-23-mdx-2.2.1.md b/data/changelog/releases/mdx/2023-01-23-mdx-2.2.1.md similarity index 100% rename from data/changelog/mdx/2023-01-23-mdx-2.2.1.md rename to data/changelog/releases/mdx/2023-01-23-mdx-2.2.1.md diff --git a/data/changelog/mdx/2023-04-17-mdx-2.3.0.md b/data/changelog/releases/mdx/2023-04-17-mdx-2.3.0.md similarity index 100% rename from data/changelog/mdx/2023-04-17-mdx-2.3.0.md rename to data/changelog/releases/mdx/2023-04-17-mdx-2.3.0.md diff --git a/data/changelog/mdx/2023-09-27-mdx-2.3.1.md b/data/changelog/releases/mdx/2023-09-27-mdx-2.3.1.md similarity index 100% rename from data/changelog/mdx/2023-09-27-mdx-2.3.1.md rename to data/changelog/releases/mdx/2023-09-27-mdx-2.3.1.md diff --git a/data/changelog/mdx/2024-03-29-mdx-2.4.0.md b/data/changelog/releases/mdx/2024-03-29-mdx-2.4.0.md similarity index 100% rename from data/changelog/mdx/2024-03-29-mdx-2.4.0.md rename to data/changelog/releases/mdx/2024-03-29-mdx-2.4.0.md diff --git a/data/changelog/mdx/2024-04-13-mdx-2.4.1.md b/data/changelog/releases/mdx/2024-04-13-mdx-2.4.1.md similarity index 100% rename from data/changelog/mdx/2024-04-13-mdx-2.4.1.md rename to data/changelog/releases/mdx/2024-04-13-mdx-2.4.1.md diff --git a/data/changelog/merlin/2013-08-11-merlin-1-3.md b/data/changelog/releases/merlin/2013-08-11-merlin-1-3.md similarity index 100% rename from data/changelog/merlin/2013-08-11-merlin-1-3.md rename to data/changelog/releases/merlin/2013-08-11-merlin-1-3.md diff --git a/data/changelog/merlin/2013-08-21-merlin-1-3-1.md b/data/changelog/releases/merlin/2013-08-21-merlin-1-3-1.md similarity index 100% rename from data/changelog/merlin/2013-08-21-merlin-1-3-1.md rename to data/changelog/releases/merlin/2013-08-21-merlin-1-3-1.md diff --git a/data/changelog/merlin/2013-09-25-merlin-1-4.md b/data/changelog/releases/merlin/2013-09-25-merlin-1-4.md similarity index 100% rename from data/changelog/merlin/2013-09-25-merlin-1-4.md rename to data/changelog/releases/merlin/2013-09-25-merlin-1-4.md diff --git a/data/changelog/merlin/2013-10-01-merlin-1-4-1.md b/data/changelog/releases/merlin/2013-10-01-merlin-1-4-1.md similarity index 100% rename from data/changelog/merlin/2013-10-01-merlin-1-4-1.md rename to data/changelog/releases/merlin/2013-10-01-merlin-1-4-1.md diff --git a/data/changelog/merlin/2013-12-17-merlin-1.5.md b/data/changelog/releases/merlin/2013-12-17-merlin-1.5.md similarity index 100% rename from data/changelog/merlin/2013-12-17-merlin-1.5.md rename to data/changelog/releases/merlin/2013-12-17-merlin-1.5.md diff --git a/data/changelog/merlin/2014-03-11-merlin-1.6.md b/data/changelog/releases/merlin/2014-03-11-merlin-1.6.md similarity index 100% rename from data/changelog/merlin/2014-03-11-merlin-1.6.md rename to data/changelog/releases/merlin/2014-03-11-merlin-1.6.md diff --git a/data/changelog/merlin/2014-08-20-merlin-1.7.md b/data/changelog/releases/merlin/2014-08-20-merlin-1.7.md similarity index 100% rename from data/changelog/merlin/2014-08-20-merlin-1.7.md rename to data/changelog/releases/merlin/2014-08-20-merlin-1.7.md diff --git a/data/changelog/merlin/2014-08-23-merlin-1.7.1.md b/data/changelog/releases/merlin/2014-08-23-merlin-1.7.1.md similarity index 100% rename from data/changelog/merlin/2014-08-23-merlin-1.7.1.md rename to data/changelog/releases/merlin/2014-08-23-merlin-1.7.1.md diff --git a/data/changelog/merlin/2014-08-23-merlin-2.0.0.md b/data/changelog/releases/merlin/2014-08-23-merlin-2.0.0.md similarity index 93% rename from data/changelog/merlin/2014-08-23-merlin-2.0.0.md rename to data/changelog/releases/merlin/2014-08-23-merlin-2.0.0.md index 5d3fef3da1..cc8d43d010 100644 --- a/data/changelog/merlin/2014-08-23-merlin-2.0.0.md +++ b/data/changelog/releases/merlin/2014-08-23-merlin-2.0.0.md @@ -12,7 +12,7 @@ changelog: | * locate now works on MLI files * automatic reloading of .merlin files (when they are update or created), it is no longer necessary to restart Merlin - * introduced a small refactoring command: rename, who renames all occurences + * introduced a small refactoring command: rename, who renames all occurrences of an identifier. This release also contains contributions from: Yotam Barnoy, Jacques-Pascal @@ -23,7 +23,7 @@ changelog: | After a few months of development, we are pleased to announce the [stable release](https://github.com/ocaml/merlin/blob/v2.0/CHANGELOG) of -[Merlin 2.0](https://github.com/the-lambda-church/merlin). +[Merlin 2.0](https://github.com/the-lambda-church/merlin). Supported OCaml versions range from 4.00.1 to 4.02.1. ### Overview @@ -41,12 +41,12 @@ available for [Sublime Text](https://github.com/def-lkb/sublime-text-merlin). ### What's new This release provides great improvements in robustness and quality of analysis. -Files that changed on disk are now automatically reloaded. +Files that changed on disk are now automatically reloaded. The parsing process is finer grained to provide more accurate recovery and error messages. Integration with Jane Street Core and js\_of\_ocaml has also improved. -Vim & Emacs are still the main targeted editors. +Vim & Emacs are still the main targeted editors. Thanks to [Luc Rocher](https://github.com/Cynddl), preliminary support for Sublime Text is also available, see [Sublime-text-merlin](https://github.com/def-lkb/sublime-text-merlin). diff --git a/data/changelog/merlin/2015-01-12-merlin-2.1.0.md b/data/changelog/releases/merlin/2015-01-12-merlin-2.1.0.md similarity index 100% rename from data/changelog/merlin/2015-01-12-merlin-2.1.0.md rename to data/changelog/releases/merlin/2015-01-12-merlin-2.1.0.md diff --git a/data/changelog/merlin/2015-01-28-merlin-2.1.1.md b/data/changelog/releases/merlin/2015-01-28-merlin-2.1.1.md similarity index 100% rename from data/changelog/merlin/2015-01-28-merlin-2.1.1.md rename to data/changelog/releases/merlin/2015-01-28-merlin-2.1.1.md diff --git a/data/changelog/merlin/2015-03-03-merlin-2.1.2.md b/data/changelog/releases/merlin/2015-03-03-merlin-2.1.2.md similarity index 100% rename from data/changelog/merlin/2015-03-03-merlin-2.1.2.md rename to data/changelog/releases/merlin/2015-03-03-merlin-2.1.2.md diff --git a/data/changelog/merlin/2015-06-10-merlin-2.2.md b/data/changelog/releases/merlin/2015-06-10-merlin-2.2.md similarity index 100% rename from data/changelog/merlin/2015-06-10-merlin-2.2.md rename to data/changelog/releases/merlin/2015-06-10-merlin-2.2.md diff --git a/data/changelog/merlin/2015-10-28-merlin-2.3.md b/data/changelog/releases/merlin/2015-10-28-merlin-2.3.md similarity index 100% rename from data/changelog/merlin/2015-10-28-merlin-2.3.md rename to data/changelog/releases/merlin/2015-10-28-merlin-2.3.md diff --git a/data/changelog/merlin/2015-11-25-merlin-2.3.1.md b/data/changelog/releases/merlin/2015-11-25-merlin-2.3.1.md similarity index 100% rename from data/changelog/merlin/2015-11-25-merlin-2.3.1.md rename to data/changelog/releases/merlin/2015-11-25-merlin-2.3.1.md diff --git a/data/changelog/merlin/2016-06-14-merlin-2.5.0.md b/data/changelog/releases/merlin/2016-06-14-merlin-2.5.0.md similarity index 100% rename from data/changelog/merlin/2016-06-14-merlin-2.5.0.md rename to data/changelog/releases/merlin/2016-06-14-merlin-2.5.0.md diff --git a/data/changelog/merlin/2016-10-18-merlin-2.5.1.md b/data/changelog/releases/merlin/2016-10-18-merlin-2.5.1.md similarity index 100% rename from data/changelog/merlin/2016-10-18-merlin-2.5.1.md rename to data/changelog/releases/merlin/2016-10-18-merlin-2.5.1.md diff --git a/data/changelog/merlin/2016-11-18-merlin-2.5.2.md b/data/changelog/releases/merlin/2016-11-18-merlin-2.5.2.md similarity index 100% rename from data/changelog/merlin/2016-11-18-merlin-2.5.2.md rename to data/changelog/releases/merlin/2016-11-18-merlin-2.5.2.md diff --git a/data/changelog/merlin/2016-11-28-merlin-2.5.3.md b/data/changelog/releases/merlin/2016-11-28-merlin-2.5.3.md similarity index 100% rename from data/changelog/merlin/2016-11-28-merlin-2.5.3.md rename to data/changelog/releases/merlin/2016-11-28-merlin-2.5.3.md diff --git a/data/changelog/merlin/2017-04-25-merlin-2.5.4.md b/data/changelog/releases/merlin/2017-04-25-merlin-2.5.4.md similarity index 100% rename from data/changelog/merlin/2017-04-25-merlin-2.5.4.md rename to data/changelog/releases/merlin/2017-04-25-merlin-2.5.4.md diff --git a/data/changelog/merlin/2017-06-14-merlin-2.5.5.md b/data/changelog/releases/merlin/2017-06-14-merlin-2.5.5.md similarity index 100% rename from data/changelog/merlin/2017-06-14-merlin-2.5.5.md rename to data/changelog/releases/merlin/2017-06-14-merlin-2.5.5.md diff --git a/data/changelog/merlin/2017-07-24-merlin-3.0.0.md b/data/changelog/releases/merlin/2017-07-24-merlin-3.0.0.md similarity index 100% rename from data/changelog/merlin/2017-07-24-merlin-3.0.0.md rename to data/changelog/releases/merlin/2017-07-24-merlin-3.0.0.md diff --git a/data/changelog/merlin/2017-07-27-merlin-3.0.1.md b/data/changelog/releases/merlin/2017-07-27-merlin-3.0.1.md similarity index 100% rename from data/changelog/merlin/2017-07-27-merlin-3.0.1.md rename to data/changelog/releases/merlin/2017-07-27-merlin-3.0.1.md diff --git a/data/changelog/merlin/2017-08-04-merlin-3.0.2.md b/data/changelog/releases/merlin/2017-08-04-merlin-3.0.2.md similarity index 100% rename from data/changelog/merlin/2017-08-04-merlin-3.0.2.md rename to data/changelog/releases/merlin/2017-08-04-merlin-3.0.2.md diff --git a/data/changelog/merlin/2017-10-02-merlin-3.0.3.md b/data/changelog/releases/merlin/2017-10-02-merlin-3.0.3.md similarity index 100% rename from data/changelog/merlin/2017-10-02-merlin-3.0.3.md rename to data/changelog/releases/merlin/2017-10-02-merlin-3.0.3.md diff --git a/data/changelog/merlin/2017-11-12-merlin-3.0.4.md b/data/changelog/releases/merlin/2017-11-12-merlin-3.0.4.md similarity index 100% rename from data/changelog/merlin/2017-11-12-merlin-3.0.4.md rename to data/changelog/releases/merlin/2017-11-12-merlin-3.0.4.md diff --git a/data/changelog/merlin/2017-11-13-merlin-3.0.5.md b/data/changelog/releases/merlin/2017-11-13-merlin-3.0.5.md similarity index 100% rename from data/changelog/merlin/2017-11-13-merlin-3.0.5.md rename to data/changelog/releases/merlin/2017-11-13-merlin-3.0.5.md diff --git a/data/changelog/merlin/2018-06-21-merlin-3.1.0.md b/data/changelog/releases/merlin/2018-06-21-merlin-3.1.0.md similarity index 100% rename from data/changelog/merlin/2018-06-21-merlin-3.1.0.md rename to data/changelog/releases/merlin/2018-06-21-merlin-3.1.0.md diff --git a/data/changelog/merlin/2018-10-08-merlin-3.2.1.md b/data/changelog/releases/merlin/2018-10-08-merlin-3.2.1.md similarity index 100% rename from data/changelog/merlin/2018-10-08-merlin-3.2.1.md rename to data/changelog/releases/merlin/2018-10-08-merlin-3.2.1.md diff --git a/data/changelog/merlin/2018-10-11-merlin-3.2.2.md b/data/changelog/releases/merlin/2018-10-11-merlin-3.2.2.md similarity index 100% rename from data/changelog/merlin/2018-10-11-merlin-3.2.2.md rename to data/changelog/releases/merlin/2018-10-11-merlin-3.2.2.md diff --git a/data/changelog/merlin/2019-06-03-merlin-3.3.0.md b/data/changelog/releases/merlin/2019-06-03-merlin-3.3.0.md similarity index 100% rename from data/changelog/merlin/2019-06-03-merlin-3.3.0.md rename to data/changelog/releases/merlin/2019-06-03-merlin-3.3.0.md diff --git a/data/changelog/merlin/2019-06-17-merlin-3.3.1.md b/data/changelog/releases/merlin/2019-06-17-merlin-3.3.1.md similarity index 100% rename from data/changelog/merlin/2019-06-17-merlin-3.3.1.md rename to data/changelog/releases/merlin/2019-06-17-merlin-3.3.1.md diff --git a/data/changelog/merlin/2019-07-15-merlin-3.3.2.md b/data/changelog/releases/merlin/2019-07-15-merlin-3.3.2.md similarity index 100% rename from data/changelog/merlin/2019-07-15-merlin-3.3.2.md rename to data/changelog/releases/merlin/2019-07-15-merlin-3.3.2.md diff --git a/data/changelog/merlin/2019-11-29-merlin-3.3.3.md b/data/changelog/releases/merlin/2019-11-29-merlin-3.3.3.md similarity index 100% rename from data/changelog/merlin/2019-11-29-merlin-3.3.3.md rename to data/changelog/releases/merlin/2019-11-29-merlin-3.3.3.md diff --git a/data/changelog/merlin/2020-04-15-merlin-3.3.4.md b/data/changelog/releases/merlin/2020-04-15-merlin-3.3.4.md similarity index 100% rename from data/changelog/merlin/2020-04-15-merlin-3.3.4.md rename to data/changelog/releases/merlin/2020-04-15-merlin-3.3.4.md diff --git a/data/changelog/merlin/2020-06-11-merlin-3.3.5.md b/data/changelog/releases/merlin/2020-06-11-merlin-3.3.5.md similarity index 100% rename from data/changelog/merlin/2020-06-11-merlin-3.3.5.md rename to data/changelog/releases/merlin/2020-06-11-merlin-3.3.5.md diff --git a/data/changelog/merlin/2020-06-12-merlin-3.3.6.md b/data/changelog/releases/merlin/2020-06-12-merlin-3.3.6.md similarity index 100% rename from data/changelog/merlin/2020-06-12-merlin-3.3.6.md rename to data/changelog/releases/merlin/2020-06-12-merlin-3.3.6.md diff --git a/data/changelog/merlin/2020-08-26-merlin-3.3.7.md b/data/changelog/releases/merlin/2020-08-26-merlin-3.3.7.md similarity index 100% rename from data/changelog/merlin/2020-08-26-merlin-3.3.7.md rename to data/changelog/releases/merlin/2020-08-26-merlin-3.3.7.md diff --git a/data/changelog/merlin/2020-08-27-merlin-3.3.8.md b/data/changelog/releases/merlin/2020-08-27-merlin-3.3.8.md similarity index 100% rename from data/changelog/merlin/2020-08-27-merlin-3.3.8.md rename to data/changelog/releases/merlin/2020-08-27-merlin-3.3.8.md diff --git a/data/changelog/merlin/2020-09-04-merlin-3.3.9.md b/data/changelog/releases/merlin/2020-09-04-merlin-3.3.9.md similarity index 100% rename from data/changelog/merlin/2020-09-04-merlin-3.3.9.md rename to data/changelog/releases/merlin/2020-09-04-merlin-3.3.9.md diff --git a/data/changelog/merlin/2020-09-17-merlin-3.4.0.md b/data/changelog/releases/merlin/2020-09-17-merlin-3.4.0.md similarity index 100% rename from data/changelog/merlin/2020-09-17-merlin-3.4.0.md rename to data/changelog/releases/merlin/2020-09-17-merlin-3.4.0.md diff --git a/data/changelog/merlin/2020-10-02-merlin-3.4.1.md b/data/changelog/releases/merlin/2020-10-02-merlin-3.4.1.md similarity index 100% rename from data/changelog/merlin/2020-10-02-merlin-3.4.1.md rename to data/changelog/releases/merlin/2020-10-02-merlin-3.4.1.md diff --git a/data/changelog/merlin/2020-11-17-merlin-3.4.2.md b/data/changelog/releases/merlin/2020-11-17-merlin-3.4.2.md similarity index 100% rename from data/changelog/merlin/2020-11-17-merlin-3.4.2.md rename to data/changelog/releases/merlin/2020-11-17-merlin-3.4.2.md diff --git a/data/changelog/merlin/2021-02-16-merlin-4.1.md b/data/changelog/releases/merlin/2021-02-16-merlin-4.1.md similarity index 100% rename from data/changelog/merlin/2021-02-16-merlin-4.1.md rename to data/changelog/releases/merlin/2021-02-16-merlin-4.1.md diff --git a/data/changelog/merlin/2021-04-14-merlin-3.5.0.md b/data/changelog/releases/merlin/2021-04-14-merlin-3.5.0.md similarity index 100% rename from data/changelog/merlin/2021-04-14-merlin-3.5.0.md rename to data/changelog/releases/merlin/2021-04-14-merlin-3.5.0.md diff --git a/data/changelog/merlin/2021-04-14-merlin-4.2.md b/data/changelog/releases/merlin/2021-04-14-merlin-4.2.md similarity index 100% rename from data/changelog/merlin/2021-04-14-merlin-4.2.md rename to data/changelog/releases/merlin/2021-04-14-merlin-4.2.md diff --git a/data/changelog/merlin/2021-07-26-merlin-3.6.1.md b/data/changelog/releases/merlin/2021-07-26-merlin-3.6.1.md similarity index 100% rename from data/changelog/merlin/2021-07-26-merlin-3.6.1.md rename to data/changelog/releases/merlin/2021-07-26-merlin-3.6.1.md diff --git a/data/changelog/merlin/2021-07-26-merlin-4.3.1.md b/data/changelog/releases/merlin/2021-07-26-merlin-4.3.1.md similarity index 100% rename from data/changelog/merlin/2021-07-26-merlin-4.3.1.md rename to data/changelog/releases/merlin/2021-07-26-merlin-4.3.1.md diff --git a/data/changelog/merlin/2021-11-23-merlin-3.7.0.md b/data/changelog/releases/merlin/2021-11-23-merlin-3.7.0.md similarity index 100% rename from data/changelog/merlin/2021-11-23-merlin-3.7.0.md rename to data/changelog/releases/merlin/2021-11-23-merlin-3.7.0.md diff --git a/data/changelog/merlin/2021-11-23-merlin-4.4.md b/data/changelog/releases/merlin/2021-11-23-merlin-4.4.md similarity index 92% rename from data/changelog/merlin/2021-11-23-merlin-4.4.md rename to data/changelog/releases/merlin/2021-11-23-merlin-4.4.md index 13ca957ee1..ab30ad4528 100644 --- a/data/changelog/merlin/2021-11-23-merlin-4.4.md +++ b/data/changelog/releases/merlin/2021-11-23-merlin-4.4.md @@ -7,7 +7,7 @@ changelog: | - stopped actively supporting version older than 4.12 + merlin binary - Mbrowse.select_leaf: correctly ignore merlin.hide (#1376) - - enable `occurences` to work when looking for locally abstract types + - enable `occurrences` to work when looking for locally abstract types (#1382) - handle `-alert` compiler flag (#1401) - avoid a race condition when the process started to read a configuration diff --git a/data/changelog/merlin/2022-04-06-merlin-4.5.md b/data/changelog/releases/merlin/2022-04-06-merlin-4.5.md similarity index 100% rename from data/changelog/merlin/2022-04-06-merlin-4.5.md rename to data/changelog/releases/merlin/2022-04-06-merlin-4.5.md diff --git a/data/changelog/merlin/2022-06-30-merlin-4.6.md b/data/changelog/releases/merlin/2022-06-30-merlin-4.6.md similarity index 100% rename from data/changelog/merlin/2022-06-30-merlin-4.6.md rename to data/changelog/releases/merlin/2022-06-30-merlin-4.6.md diff --git a/data/changelog/merlin/2022-07-07-merlin-3.8.0.md b/data/changelog/releases/merlin/2022-07-07-merlin-3.8.0.md similarity index 100% rename from data/changelog/merlin/2022-07-07-merlin-3.8.0.md rename to data/changelog/releases/merlin/2022-07-07-merlin-3.8.0.md diff --git a/data/changelog/merlin/2022-11-25-merlin-4.7.md b/data/changelog/releases/merlin/2022-11-25-merlin-4.7.md similarity index 100% rename from data/changelog/merlin/2022-11-25-merlin-4.7.md rename to data/changelog/releases/merlin/2022-11-25-merlin-4.7.md diff --git a/data/changelog/merlin/2022-12-13-merlin-4.7.1.md b/data/changelog/releases/merlin/2022-12-13-merlin-4.7.1.md similarity index 100% rename from data/changelog/merlin/2022-12-13-merlin-4.7.1.md rename to data/changelog/releases/merlin/2022-12-13-merlin-4.7.1.md diff --git a/data/changelog/merlin/2023-02-27-merlin-4.8.md b/data/changelog/releases/merlin/2023-02-27-merlin-4.8.md similarity index 100% rename from data/changelog/merlin/2023-02-27-merlin-4.8.md rename to data/changelog/releases/merlin/2023-02-27-merlin-4.8.md diff --git a/data/changelog/merlin/2023-05-31-merlin-4.9.md b/data/changelog/releases/merlin/2023-05-31-merlin-4.9.md similarity index 100% rename from data/changelog/merlin/2023-05-31-merlin-4.9.md rename to data/changelog/releases/merlin/2023-05-31-merlin-4.9.md diff --git a/data/changelog/merlin/2023-08-29-merlin-4.10.md b/data/changelog/releases/merlin/2023-08-29-merlin-4.10.md similarity index 100% rename from data/changelog/merlin/2023-08-29-merlin-4.10.md rename to data/changelog/releases/merlin/2023-08-29-merlin-4.10.md diff --git a/data/changelog/merlin/2023-09-22-merlin-4.11.md b/data/changelog/releases/merlin/2023-09-22-merlin-4.11.md similarity index 100% rename from data/changelog/merlin/2023-09-22-merlin-4.11.md rename to data/changelog/releases/merlin/2023-09-22-merlin-4.11.md diff --git a/data/changelog/merlin/2023-09-26-merlin-4.12.md b/data/changelog/releases/merlin/2023-09-26-merlin-4.12.md similarity index 100% rename from data/changelog/merlin/2023-09-26-merlin-4.12.md rename to data/changelog/releases/merlin/2023-09-26-merlin-4.12.md diff --git a/data/changelog/merlin/2023-12-06-merlin-4.13.md b/data/changelog/releases/merlin/2023-12-06-merlin-4.13.md similarity index 100% rename from data/changelog/merlin/2023-12-06-merlin-4.13.md rename to data/changelog/releases/merlin/2023-12-06-merlin-4.13.md diff --git a/data/changelog/merlin/2024-02-26-merlin-4.14.md b/data/changelog/releases/merlin/2024-02-26-merlin-4.14.md similarity index 100% rename from data/changelog/merlin/2024-02-26-merlin-4.14.md rename to data/changelog/releases/merlin/2024-02-26-merlin-4.14.md diff --git a/data/changelog/merlin/2024-05-22-merlin-5.0.md b/data/changelog/releases/merlin/2024-05-22-merlin-5.0.md similarity index 100% rename from data/changelog/merlin/2024-05-22-merlin-5.0.md rename to data/changelog/releases/merlin/2024-05-22-merlin-5.0.md diff --git a/data/changelog/merlin/2024-06-03-merlin-54.15.md b/data/changelog/releases/merlin/2024-06-03-merlin-54.15.md similarity index 100% rename from data/changelog/merlin/2024-06-03-merlin-54.15.md rename to data/changelog/releases/merlin/2024-06-03-merlin-54.15.md diff --git a/data/changelog/merlin/2024-06-12-merlin-4.16.md b/data/changelog/releases/merlin/2024-06-12-merlin-4.16.md similarity index 100% rename from data/changelog/merlin/2024-06-12-merlin-4.16.md rename to data/changelog/releases/merlin/2024-06-12-merlin-4.16.md diff --git a/data/changelog/merlin/2024-06-24-merlin-5.1.md b/data/changelog/releases/merlin/2024-06-24-merlin-5.1.md similarity index 100% rename from data/changelog/merlin/2024-06-24-merlin-5.1.md rename to data/changelog/releases/merlin/2024-06-24-merlin-5.1.md diff --git a/data/changelog/merlin/2024-09-27-merlin-5.2.1.md b/data/changelog/releases/merlin/2024-09-27-merlin-5.2.1.md similarity index 100% rename from data/changelog/merlin/2024-09-27-merlin-5.2.1.md rename to data/changelog/releases/merlin/2024-09-27-merlin-5.2.1.md diff --git a/data/changelog/merlin/2024-23-12-merlin-5.3.502-and-4.18.414.md b/data/changelog/releases/merlin/2024-12-23-merlin-5.3.502-and-4.18.414.md similarity index 100% rename from data/changelog/merlin/2024-23-12-merlin-5.3.502-and-4.18.414.md rename to data/changelog/releases/merlin/2024-12-23-merlin-5.3.502-and-4.18.414.md diff --git a/data/changelog/ocaml-lsp/2020-10-15-ocaml-lsp-1.1.0.md b/data/changelog/releases/ocaml-lsp/2020-10-15-ocaml-lsp-1.1.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2020-10-15-ocaml-lsp-1.1.0.md rename to data/changelog/releases/ocaml-lsp/2020-10-15-ocaml-lsp-1.1.0.md diff --git a/data/changelog/ocaml-lsp/2020-11-18-ocaml-lsp-1.2.0.md b/data/changelog/releases/ocaml-lsp/2020-11-18-ocaml-lsp-1.2.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2020-11-18-ocaml-lsp-1.2.0.md rename to data/changelog/releases/ocaml-lsp/2020-11-18-ocaml-lsp-1.2.0.md diff --git a/data/changelog/ocaml-lsp/2020-11-26-ocaml-lsp-1.3.0.md b/data/changelog/releases/ocaml-lsp/2020-11-26-ocaml-lsp-1.3.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2020-11-26-ocaml-lsp-1.3.0.md rename to data/changelog/releases/ocaml-lsp/2020-11-26-ocaml-lsp-1.3.0.md diff --git a/data/changelog/ocaml-lsp/2020-12-18-ocaml-lsp-1.4.0.md b/data/changelog/releases/ocaml-lsp/2020-12-18-ocaml-lsp-1.4.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2020-12-18-ocaml-lsp-1.4.0.md rename to data/changelog/releases/ocaml-lsp/2020-12-18-ocaml-lsp-1.4.0.md diff --git a/data/changelog/ocaml-lsp/2021-03-18-ocaml-lsp-1.4.1.md b/data/changelog/releases/ocaml-lsp/2021-03-18-ocaml-lsp-1.4.1.md similarity index 100% rename from data/changelog/ocaml-lsp/2021-03-18-ocaml-lsp-1.4.1.md rename to data/changelog/releases/ocaml-lsp/2021-03-18-ocaml-lsp-1.4.1.md diff --git a/data/changelog/ocaml-lsp/2021-03-31-ocaml-lsp-1.5.0.md b/data/changelog/releases/ocaml-lsp/2021-03-31-ocaml-lsp-1.5.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2021-03-31-ocaml-lsp-1.5.0.md rename to data/changelog/releases/ocaml-lsp/2021-03-31-ocaml-lsp-1.5.0.md diff --git a/data/changelog/ocaml-lsp/2021-05-03-ocaml-lsp-1.6.0.md b/data/changelog/releases/ocaml-lsp/2021-05-03-ocaml-lsp-1.6.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2021-05-03-ocaml-lsp-1.6.0.md rename to data/changelog/releases/ocaml-lsp/2021-05-03-ocaml-lsp-1.6.0.md diff --git a/data/changelog/ocaml-lsp/2021-05-19-ocaml-lsp-1.6.1.md b/data/changelog/releases/ocaml-lsp/2021-05-19-ocaml-lsp-1.6.1.md similarity index 100% rename from data/changelog/ocaml-lsp/2021-05-19-ocaml-lsp-1.6.1.md rename to data/changelog/releases/ocaml-lsp/2021-05-19-ocaml-lsp-1.6.1.md diff --git a/data/changelog/ocaml-lsp/2021-06-29-ocaml-lsp-1.7.0.md b/data/changelog/releases/ocaml-lsp/2021-06-29-ocaml-lsp-1.7.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2021-06-29-ocaml-lsp-1.7.0.md rename to data/changelog/releases/ocaml-lsp/2021-06-29-ocaml-lsp-1.7.0.md diff --git a/data/changelog/ocaml-lsp/2021-09-10-ocaml-lsp-1.8.0.md b/data/changelog/releases/ocaml-lsp/2021-09-10-ocaml-lsp-1.8.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2021-09-10-ocaml-lsp-1.8.0.md rename to data/changelog/releases/ocaml-lsp/2021-09-10-ocaml-lsp-1.8.0.md diff --git a/data/changelog/ocaml-lsp/2021-09-14-ocaml-lsp-1.8.2.md b/data/changelog/releases/ocaml-lsp/2021-09-14-ocaml-lsp-1.8.2.md similarity index 100% rename from data/changelog/ocaml-lsp/2021-09-14-ocaml-lsp-1.8.2.md rename to data/changelog/releases/ocaml-lsp/2021-09-14-ocaml-lsp-1.8.2.md diff --git a/data/changelog/ocaml-lsp/2021-10-05-ocaml-lsp-1.8.3.md b/data/changelog/releases/ocaml-lsp/2021-10-05-ocaml-lsp-1.8.3.md similarity index 100% rename from data/changelog/ocaml-lsp/2021-10-05-ocaml-lsp-1.8.3.md rename to data/changelog/releases/ocaml-lsp/2021-10-05-ocaml-lsp-1.8.3.md diff --git a/data/changelog/ocaml-lsp/2021-11-21-ocaml-lsp-1.9.0.md b/data/changelog/releases/ocaml-lsp/2021-11-21-ocaml-lsp-1.9.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2021-11-21-ocaml-lsp-1.9.0.md rename to data/changelog/releases/ocaml-lsp/2021-11-21-ocaml-lsp-1.9.0.md diff --git a/data/changelog/ocaml-lsp/2021-11-26-ocaml-lsp-1.9.1.md b/data/changelog/releases/ocaml-lsp/2021-11-26-ocaml-lsp-1.9.1.md similarity index 100% rename from data/changelog/ocaml-lsp/2021-11-26-ocaml-lsp-1.9.1.md rename to data/changelog/releases/ocaml-lsp/2021-11-26-ocaml-lsp-1.9.1.md diff --git a/data/changelog/ocaml-lsp/2022-02-11-ocaml-lsp-1.10.0.md b/data/changelog/releases/ocaml-lsp/2022-02-11-ocaml-lsp-1.10.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-02-11-ocaml-lsp-1.10.0.md rename to data/changelog/releases/ocaml-lsp/2022-02-11-ocaml-lsp-1.10.0.md diff --git a/data/changelog/ocaml-lsp/2022-02-12-ocaml-lsp-1.10.1.md b/data/changelog/releases/ocaml-lsp/2022-02-12-ocaml-lsp-1.10.1.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-02-12-ocaml-lsp-1.10.1.md rename to data/changelog/releases/ocaml-lsp/2022-02-12-ocaml-lsp-1.10.1.md diff --git a/data/changelog/ocaml-lsp/2022-02-20-ocaml-lsp-1.10.2.md b/data/changelog/releases/ocaml-lsp/2022-02-20-ocaml-lsp-1.10.2.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-02-20-ocaml-lsp-1.10.2.md rename to data/changelog/releases/ocaml-lsp/2022-02-20-ocaml-lsp-1.10.2.md diff --git a/data/changelog/ocaml-lsp/2022-02-24-ocaml-lsp-1.10.3.md b/data/changelog/releases/ocaml-lsp/2022-02-24-ocaml-lsp-1.10.3.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-02-24-ocaml-lsp-1.10.3.md rename to data/changelog/releases/ocaml-lsp/2022-02-24-ocaml-lsp-1.10.3.md diff --git a/data/changelog/ocaml-lsp/2022-04-07-ocaml-lsp-1.10.5.md b/data/changelog/releases/ocaml-lsp/2022-04-07-ocaml-lsp-1.10.5.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-04-07-ocaml-lsp-1.10.5.md rename to data/changelog/releases/ocaml-lsp/2022-04-07-ocaml-lsp-1.10.5.md diff --git a/data/changelog/ocaml-lsp/2022-04-08-ocaml-lsp-1.10.6.md b/data/changelog/releases/ocaml-lsp/2022-04-08-ocaml-lsp-1.10.6.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-04-08-ocaml-lsp-1.10.6.md rename to data/changelog/releases/ocaml-lsp/2022-04-08-ocaml-lsp-1.10.6.md diff --git a/data/changelog/ocaml-lsp/2022-04-15-ocaml-lsp-1.11.0.md b/data/changelog/releases/ocaml-lsp/2022-04-15-ocaml-lsp-1.11.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-04-15-ocaml-lsp-1.11.0.md rename to data/changelog/releases/ocaml-lsp/2022-04-15-ocaml-lsp-1.11.0.md diff --git a/data/changelog/ocaml-lsp/2022-04-18-ocaml-lsp-1.11.1.md b/data/changelog/releases/ocaml-lsp/2022-04-18-ocaml-lsp-1.11.1.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-04-18-ocaml-lsp-1.11.1.md rename to data/changelog/releases/ocaml-lsp/2022-04-18-ocaml-lsp-1.11.1.md diff --git a/data/changelog/ocaml-lsp/2022-04-20-ocaml-lsp-1.11.2.md b/data/changelog/releases/ocaml-lsp/2022-04-20-ocaml-lsp-1.11.2.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-04-20-ocaml-lsp-1.11.2.md rename to data/changelog/releases/ocaml-lsp/2022-04-20-ocaml-lsp-1.11.2.md diff --git a/data/changelog/ocaml-lsp/2022-04-23-ocaml-lsp-1.11.3.md b/data/changelog/releases/ocaml-lsp/2022-04-23-ocaml-lsp-1.11.3.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-04-23-ocaml-lsp-1.11.3.md rename to data/changelog/releases/ocaml-lsp/2022-04-23-ocaml-lsp-1.11.3.md diff --git a/data/changelog/ocaml-lsp/2022-04-26-ocaml-lsp-1.11.4.md b/data/changelog/releases/ocaml-lsp/2022-04-26-ocaml-lsp-1.11.4.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-04-26-ocaml-lsp-1.11.4.md rename to data/changelog/releases/ocaml-lsp/2022-04-26-ocaml-lsp-1.11.4.md diff --git a/data/changelog/ocaml-lsp/2022-05-13-ocaml-lsp-1.11.5.md b/data/changelog/releases/ocaml-lsp/2022-05-13-ocaml-lsp-1.11.5.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-05-13-ocaml-lsp-1.11.5.md rename to data/changelog/releases/ocaml-lsp/2022-05-13-ocaml-lsp-1.11.5.md diff --git a/data/changelog/ocaml-lsp/2022-05-20-ocaml-lsp-1.11.6.md b/data/changelog/releases/ocaml-lsp/2022-05-20-ocaml-lsp-1.11.6.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-05-20-ocaml-lsp-1.11.6.md rename to data/changelog/releases/ocaml-lsp/2022-05-20-ocaml-lsp-1.11.6.md diff --git a/data/changelog/ocaml-lsp/2022-06-23-ocaml-lsp-1.12.0.md b/data/changelog/releases/ocaml-lsp/2022-06-23-ocaml-lsp-1.12.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-06-23-ocaml-lsp-1.12.0.md rename to data/changelog/releases/ocaml-lsp/2022-06-23-ocaml-lsp-1.12.0.md diff --git a/data/changelog/ocaml-lsp/2022-06-23-ocaml-lsp-1.12.1.md b/data/changelog/releases/ocaml-lsp/2022-06-23-ocaml-lsp-1.12.1.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-06-23-ocaml-lsp-1.12.1.md rename to data/changelog/releases/ocaml-lsp/2022-06-23-ocaml-lsp-1.12.1.md diff --git a/data/changelog/ocaml-lsp/2022-06-27-ocaml-lsp-1.12.2.md b/data/changelog/releases/ocaml-lsp/2022-06-27-ocaml-lsp-1.12.2.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-06-27-ocaml-lsp-1.12.2.md rename to data/changelog/releases/ocaml-lsp/2022-06-27-ocaml-lsp-1.12.2.md diff --git a/data/changelog/ocaml-lsp/2022-07-12-ocaml-lsp-1.12.3.md b/data/changelog/releases/ocaml-lsp/2022-07-12-ocaml-lsp-1.12.3.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-07-12-ocaml-lsp-1.12.3.md rename to data/changelog/releases/ocaml-lsp/2022-07-12-ocaml-lsp-1.12.3.md diff --git a/data/changelog/ocaml-lsp/2022-07-16-ocaml-lsp-1.12.4.md b/data/changelog/releases/ocaml-lsp/2022-07-16-ocaml-lsp-1.12.4.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-07-16-ocaml-lsp-1.12.4.md rename to data/changelog/releases/ocaml-lsp/2022-07-16-ocaml-lsp-1.12.4.md diff --git a/data/changelog/ocaml-lsp/2022-07-28-ocaml-lsp-1.13.0.md b/data/changelog/releases/ocaml-lsp/2022-07-28-ocaml-lsp-1.13.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-07-28-ocaml-lsp-1.13.0.md rename to data/changelog/releases/ocaml-lsp/2022-07-28-ocaml-lsp-1.13.0.md diff --git a/data/changelog/ocaml-lsp/2022-07-28-ocaml-lsp-1.13.1.md b/data/changelog/releases/ocaml-lsp/2022-07-28-ocaml-lsp-1.13.1.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-07-28-ocaml-lsp-1.13.1.md rename to data/changelog/releases/ocaml-lsp/2022-07-28-ocaml-lsp-1.13.1.md diff --git a/data/changelog/ocaml-lsp/2022-10-17-ocaml-lsp-1.14.0.md b/data/changelog/releases/ocaml-lsp/2022-10-17-ocaml-lsp-1.14.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-10-17-ocaml-lsp-1.14.0.md rename to data/changelog/releases/ocaml-lsp/2022-10-17-ocaml-lsp-1.14.0.md diff --git a/data/changelog/ocaml-lsp/2022-10-21-ocaml-lsp-1.14.1.md b/data/changelog/releases/ocaml-lsp/2022-10-21-ocaml-lsp-1.14.1.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-10-21-ocaml-lsp-1.14.1.md rename to data/changelog/releases/ocaml-lsp/2022-10-21-ocaml-lsp-1.14.1.md diff --git a/data/changelog/ocaml-lsp/2022-11-07-ocaml-lsp-1.14.2.md b/data/changelog/releases/ocaml-lsp/2022-11-07-ocaml-lsp-1.14.2.md similarity index 100% rename from data/changelog/ocaml-lsp/2022-11-07-ocaml-lsp-1.14.2.md rename to data/changelog/releases/ocaml-lsp/2022-11-07-ocaml-lsp-1.14.2.md diff --git a/data/changelog/ocaml-lsp/2023-01-09-ocaml-lsp-1.15.0.md b/data/changelog/releases/ocaml-lsp/2023-01-09-ocaml-lsp-1.15.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2023-01-09-ocaml-lsp-1.15.0.md rename to data/changelog/releases/ocaml-lsp/2023-01-09-ocaml-lsp-1.15.0.md diff --git a/data/changelog/ocaml-lsp/2023-01-19-ocaml-lsp-1.15.1.md b/data/changelog/releases/ocaml-lsp/2023-01-19-ocaml-lsp-1.15.1.md similarity index 100% rename from data/changelog/ocaml-lsp/2023-01-19-ocaml-lsp-1.15.1.md rename to data/changelog/releases/ocaml-lsp/2023-01-19-ocaml-lsp-1.15.1.md diff --git a/data/changelog/ocaml-lsp/2023-06-21-ocaml-lsp-1.16.1.md b/data/changelog/releases/ocaml-lsp/2023-06-21-ocaml-lsp-1.16.1.md similarity index 100% rename from data/changelog/ocaml-lsp/2023-06-21-ocaml-lsp-1.16.1.md rename to data/changelog/releases/ocaml-lsp/2023-06-21-ocaml-lsp-1.16.1.md diff --git a/data/changelog/ocaml-lsp/2023-06-23-ocaml-lsp-1.16.2.md b/data/changelog/releases/ocaml-lsp/2023-06-23-ocaml-lsp-1.16.2.md similarity index 100% rename from data/changelog/ocaml-lsp/2023-06-23-ocaml-lsp-1.16.2.md rename to data/changelog/releases/ocaml-lsp/2023-06-23-ocaml-lsp-1.16.2.md diff --git a/data/changelog/ocaml-lsp/2023-12-18-ocaml-lsp-1.17.0.md b/data/changelog/releases/ocaml-lsp/2023-12-18-ocaml-lsp-1.17.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2023-12-18-ocaml-lsp-1.17.0.md rename to data/changelog/releases/ocaml-lsp/2023-12-18-ocaml-lsp-1.17.0.md diff --git a/data/changelog/ocaml-lsp/2024-07-11-ocaml-lsp-1.18.0.md b/data/changelog/releases/ocaml-lsp/2024-07-11-ocaml-lsp-1.18.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2024-07-11-ocaml-lsp-1.18.0.md rename to data/changelog/releases/ocaml-lsp/2024-07-11-ocaml-lsp-1.18.0.md diff --git a/data/changelog/ocaml-lsp/2024-07-31-ocaml-lsp-1.19.0.md b/data/changelog/releases/ocaml-lsp/2024-07-31-ocaml-lsp-1.19.0.md similarity index 100% rename from data/changelog/ocaml-lsp/2024-07-31-ocaml-lsp-1.19.0.md rename to data/changelog/releases/ocaml-lsp/2024-07-31-ocaml-lsp-1.19.0.md diff --git a/data/changelog/ocaml-lsp/2024-12-23-ocaml-lsp-1.20.1.md b/data/changelog/releases/ocaml-lsp/2024-12-23-ocaml-lsp-1.20.1.md similarity index 100% rename from data/changelog/ocaml-lsp/2024-12-23-ocaml-lsp-1.20.1.md rename to data/changelog/releases/ocaml-lsp/2024-12-23-ocaml-lsp-1.20.1.md diff --git a/data/changelog/ocaml/2022-12-16-ocaml-5.0.md b/data/changelog/releases/ocaml/2022-12-16-ocaml-5.0.md similarity index 100% rename from data/changelog/ocaml/2022-12-16-ocaml-5.0.md rename to data/changelog/releases/ocaml/2022-12-16-ocaml-5.0.md diff --git a/data/changelog/ocaml/2022-12-20-ocaml-4.14.1.md b/data/changelog/releases/ocaml/2022-12-20-ocaml-4.14.1.md similarity index 100% rename from data/changelog/ocaml/2022-12-20-ocaml-4.14.1.md rename to data/changelog/releases/ocaml/2022-12-20-ocaml-4.14.1.md diff --git a/data/changelog/ocaml/2023-09-14-ocaml-5.1.0.md b/data/changelog/releases/ocaml/2023-09-14-ocaml-5.1.0.md similarity index 99% rename from data/changelog/ocaml/2023-09-14-ocaml-5.1.0.md rename to data/changelog/releases/ocaml/2023-09-14-ocaml-5.1.0.md index 6f2b3a2c86..8482a0fa2a 100644 --- a/data/changelog/ocaml/2023-09-14-ocaml-5.1.0.md +++ b/data/changelog/releases/ocaml/2023-09-14-ocaml-5.1.0.md @@ -37,7 +37,7 @@ changelog: | `Seq.find_mapi`, `Seq.find_index`, `Array.find_mapi`, `Array.find_index`, `Float.Array.find_opt`, `Float.Array.find_index`, `Float.Array.find_map`, `Float.Array.find_mapi`. - (Sima Kinsart, review by Daniel Bünzli and Nicolás Ojeda Bär) + (T. Kinsart, review by Daniel Bünzli and Nicolás Ojeda Bär) - [#11410](https://github.com/ocaml/ocaml/issues/11410): Add Set.to_list, Map.to_list, Map.of_list, `Map.add_to_list: key -> 'a -> 'a list t -> 'a list t`. diff --git a/data/changelog/ocaml/2023-12-8-ocaml-5.1.1.md b/data/changelog/releases/ocaml/2023-12-8-ocaml-5.1.1.md similarity index 100% rename from data/changelog/ocaml/2023-12-8-ocaml-5.1.1.md rename to data/changelog/releases/ocaml/2023-12-8-ocaml-5.1.1.md diff --git a/data/changelog/ocaml/2024-05-13-ocaml-5.2.0.md b/data/changelog/releases/ocaml/2024-05-13-ocaml-5.2.0.md similarity index 98% rename from data/changelog/ocaml/2024-05-13-ocaml-5.2.0.md rename to data/changelog/releases/ocaml/2024-05-13-ocaml-5.2.0.md index 627512680a..9cc5882cd1 100644 --- a/data/changelog/ocaml/2024-05-13-ocaml-5.2.0.md +++ b/data/changelog/releases/ocaml/2024-05-13-ocaml-5.2.0.md @@ -3,20 +3,20 @@ title: Release of OCaml 5.2.0 description: Release of OCaml 5.2.0 tags: [ocaml] changelog: | - + (Changes that can break existing programs are marked with a "*") - + ### Restored and New Backends: - + - [#12276](https://github.com/ocaml/ocaml/issues/12276), [#12601](https://github.com/ocaml/ocaml/issues/12601): Native-code compilation for POWER (64 bits, little-endian) (Xavier Leroy, review by KC Sivaramakrishnan, Anil Madhavapeddy, and Stephen Dolan) - + - [#12667](https://github.com/ocaml/ocaml/issues/12667): Extend the latter to POWER 64 bits, big-endian, ELFv2 ABI (A. Wilcox, review by Xavier Leroy) - + ### Runtime System: - + - [#12193](https://github.com/ocaml/ocaml/issues/12193): Reintroduce GC compaction for shared pools. Adds a parallel compactor for the shared pools (which contain major heap blocks sized less than 128 words). Explicit only for now, on calls to @@ -24,69 +24,69 @@ changelog: | (Sadiq Jaffer, Nick Barnes, review by Anil Madhavapeddy, Damien Doligez, David Allsopp, Miod Vallat, Artem Pianykh, Stephen Dolan, Mark Shinwell, and KC Sivaramakrishnan) - + - [#12114](https://github.com/ocaml/ocaml/issues/12114): Add ThreadSanitizer support (Fabrice Buoro and Olivier Nicole, based on an initial work by Anmol Sahoo, review by Damien Doligez, Sébastien Hinderer, Jacques-Henri Jourdan, Luc Maranget, Guillaume Munch-Maccagnoni, Gabriel Scherer) - - + + - [#12850](https://github.com/ocaml/ocaml/issues/12850): Update `Gc.quick_stat` data at the end of major cycles and compaction. This PR adds an additional `caml_collect_gc_stats_sample_stw` to the major heap cycling STW. This means that `Gc.quick_stat` now actually reflects the state of the heap after a major cycle or compaction. (Sadiq Jaffer, review by Miod Vallat and Gabriel Scherer) - + - [#12859](https://github.com/ocaml/ocaml/issues/12859): Ensure `Gc.compact` does a full major before the compactor runs (Sadiq Jaffer, review by Leo White, Mark Shinwell, Gabriel Scherer, Josh Berdine, David Allsopp, and KC Sivaramakrishnan) - + - [#10111](https://github.com/ocaml/ocaml/issues/10111): Increase the detail of location information for debugging events to allow the end-line number and character offset to be reported. (David Allsopp, review by Nick Barnes, Enguerrand Decorne and Stephen Dolan) - + - [#10403](https://github.com/ocaml/ocaml/issues/10403), [#12202](https://github.com/ocaml/ocaml/issues/12202): Introduce `caml_ext_table_add_noexc` that does not raise `Out_of_memory` exceptions, and use it inside the blocking sections of `caml_read_directory`. Also, check for overflows in EXT table sizes. (Xavier Leroy, report by Arseniy Alekseyev, review by Gabriel Scherer) - + - [#11332](https://github.com/ocaml/ocaml/issues/11332), [#12702](https://github.com/ocaml/ocaml/issues/12702): Make sure `Bool_val(v)` has type `bool` in C++ (Xavier Leroy, report by ygrek, review by Gabriel Scherer) - + - [#12772](https://github.com/ocaml/ocaml/issues/12772), [#12787](https://github.com/ocaml/ocaml/issues/12787): Avoid using `_Bool` in public headers for the sake of C++ compatibility (Guillaume Munch-Maccagnoni, report by KC Sivaramakrishnan, review by Xavier Leroy and KC Sivaramakrishnan) - + - [#12223](https://github.com/ocaml/ocaml/issues/12223): Constify constructors and flags tables in C code. Now these tables will go in the read-only segment where they belong. (Antonin Décimo, review by Gabriel Scherer and Xavier Leroy) - + - [#12234](https://github.com/ocaml/ocaml/issues/12234): Make instrumented time calculation more thread-safe on macOS. (Anil Madhavapeddy, review by Daniel Bünzli and Xavier Leroy) - + - [#12235](https://github.com/ocaml/ocaml/issues/12235), [#12468](https://github.com/ocaml/ocaml/issues/12468): Introduce and use the `CAMLnoret` macro as a lighter alternative to `CAMLnoreturn_start` / `CAMLnoreturn_end`. Implement it so as to conform with C11, C23, C++11, C++17. (Xavier Leroy and Dhruv Maroo, with help from Antonin Décimo, review by Gabriel Scherer and David Allsopp) - + - [#12275](https://github.com/ocaml/ocaml/issues/12275): `caml/stack.h`: More abstract macros to describe OCaml stacks and how to traverse them, supporting more stack layouts. (Xavier Leroy, review by KC Sivaramakrishnan and Fabrice Buoro) - + - [#12268](https://github.com/ocaml/ocaml/issues/12268): Deliver `Out_of_memory` exception if domain creation fails due to memory resource exhaustion. Previously, it was always a `Failure`. (Anil Madhavapeddy, review by David Allsopp) - + - [#12300](https://github.com/ocaml/ocaml/issues/12300), [#12314](https://github.com/ocaml/ocaml/issues/12314): Discard `out_channel` buffered data on permanent I/O error (Xavier Leroy, report by Török Edwin, review by Anil Madhavapeddy and Nicolás Ojeda Bär) - + - [#11386](https://github.com/ocaml/ocaml/issues/11386): Simplifications and fixes to Multicore systhreads implementation. (Guillaume Munch-Maccagnoni, review by Anil Madhavapeddy and KC Sivaramakrishnan) - + - [#12875](https://github.com/ocaml/ocaml/issues/12875), [#12879](https://github.com/ocaml/ocaml/issues/12879), [#12882](https://github.com/ocaml/ocaml/issues/12882): Execute preemptive systhread switching as a delayed pending action. This ensures that one can reason within the FFI that no mutation happens on the same domain when allocating on @@ -94,28 +94,28 @@ changelog: | further bugs with the Multicore systhreads implementation. (Guillaume Munch-Maccagnoni, bug reports and suggestion by Mark Shinwell, review by Nick Barnes and Stephen Dolan) - + - [#12408](https://github.com/ocaml/ocaml/issues/12408): `Domain.spawn` no longer leaks its functional argument for the whole duration of the children's domain lifetime. (Guillaume Munch-Maccagnoni, review by Gabriel Scherer) - + - [#12409](https://github.com/ocaml/ocaml/issues/12409): Fix unsafety and deadlocks should an asynchronous exception arise at specific locations during domain creation and shutdown. (Guillaume Munch-Maccagnoni, review by Gabriel Scherer) - + - [#11911](https://github.com/ocaml/ocaml/issues/11911), [#12381](https://github.com/ocaml/ocaml/issues/12381): Restore `statmemprof` functionality in part, with some API changes in `Gc.Memprof`. (Nick Barnes, review by Jacques-Henri Jourdan and Guillaume Munch-Maccagnoni). - + - [#12430](https://github.com/ocaml/ocaml/issues/12430): Simplify dynamic bytecode loading in `Meta.reify_bytecode` (Stephen Dolan, review by Sébastien Hinderer, Vincent Laviron and Xavier Leroy) - + - [#12489](https://github.com/ocaml/ocaml/issues/12489): Fix an error-handling bug in `caml_alloc_sprintf` (Stephen Dolan, report by Chris Casinghino, review by Jeremy Yallop and Xavier Leroy) - + - [#11307](https://github.com/ocaml/ocaml/issues/11307): Finish adapting the implementation of asynchronous actions for Multicore: soundness, liveness, and performance issues. Do not crash if a signal handler is called from an unregistered C @@ -125,102 +125,102 @@ changelog: | immediately. (Guillaume Munch-Maccagnoni, review by Enguerrand Decorne, Xavier Leroy, and KC Sivaramakrishnan) - + - [#12634](https://github.com/ocaml/ocaml/issues/12634): Simplify TSan backtrace bookkeeping upon raise (Olivier Nicole and Fabrice Buoro, review by Gabriel Scherer) - + * (*Breaking Change*) [#12686](https://github.com/ocaml/ocaml/issues/12686): Some primitives had the wrong types to be callable from the bytecode interpreter. Either fix their types, mark them as `CAMLexport` instead of `CAMLprim`, or remove them entirely if no longer used. (Xavier Leroy, review by David Allsopp) - + - [#12700](https://github.com/ocaml/ocaml/issues/12700), continuing [#11763](https://github.com/ocaml/ocaml/issues/11763) and trying to address [#12660](https://github.com/ocaml/ocaml/issues/12660): Use the correct types for primitives when generating the table of primitives used by `ocamlrun`. (Xavier Leroy, motivation, review and improvements by Antonin Décimo) - + - [#12345](https://github.com/ocaml/ocaml/issues/12345), [#12710](https://github.com/ocaml/ocaml/issues/12710): Fix issues with finaliser orphaning at domain termination (KC Sivaramakrishnan, report by Gabriel Scherer, review by Gabriel Scherer, Sadiq Jaffer and Fabrice Buoro) - + - [#12599](https://github.com/ocaml/ocaml/issues/12599): Refactor Dynlink startup to avoid parsing bytecode sections twice (Stephen Dolan, review by David Allsopp, Hugo Heuzard, Damien Doligez and Xavier Leroy) - + - [#12678](https://github.com/ocaml/ocaml/issues/12678), [#12898](https://github.com/ocaml/ocaml/issues/12898): Free channel buffers on close rather than on finalisation (Damien Doligez, review by Jan Midtgaard and Gabriel Scherer, report by Jan Midtgaard) - + - [#12681](https://github.com/ocaml/ocaml/issues/12681): Fix TSan false positives due to volatile write handling (Olivier Nicole, Fabrice Buoro, and Anmol Sahoo, review by Luc Maranget, Gabriel Scherer, Hernan Ponce de Leon, and Xavier Leroy) - + - [#12743](https://github.com/ocaml/ocaml/issues/12743): Use `pthread_sigmask` instead of `sigprocmask`. Updates usage of `sigprocmask` to `pthread_sigmask` in `otherlibs/unix`. (Max Slater, review by Miod Vallat and Xavier Leroy) - + - [#12769](https://github.com/ocaml/ocaml/issues/12769): Unify MSVC and MinGW-w64 code paths, by always using WinAPI directly. (David Allsopp, Antonin Décimo, and Samuel Hym, review by Nicolas Ojeda Bar) - + - [#11911](https://github.com/ocaml/ocaml/issues/11911), [#12382](https://github.com/ocaml/ocaml/issues/12382), [#12383](https://github.com/ocaml/ocaml/issues/12383): Restore `statmemprof` functionality in part (backtrace buffers, per-thread and per-domain data structures, GC/allocation interface). (Nick Barnes, review by Gabriel Scherer, Fabrice Buoro, Sadiq Jaffer, Guillaume Munch-Maccagnoni, and Jacques-Henri Jourdan). - + - [#12735](https://github.com/ocaml/ocaml/issues/12735): Store both ends of the stack chain in continuations (Leo White, review by Miod Vallat and KC Sivaramakrishnan) - + - [#12746](https://github.com/ocaml/ocaml/issues/12746): Simplify and clean up TSan annotations (Olivier Nicole, review by Miod Vallat and Fabrice Buoro) - + - [#12809](https://github.com/ocaml/ocaml/issues/12809): Add ThreadSanitizer support to FreeBSD/AMD64 (Miod Vallat, review by Gabriel Scherer) - + - [#12810](https://github.com/ocaml/ocaml/issues/12810): Port ThreadSanitizer support to Linux and macOS on arm64 (Miod Vallat, review by Tim McGilchrist) - + - [#12811](https://github.com/ocaml/ocaml/issues/12811): Define and use the CAMLthread_local macro for TLS variables. (Antonin Décimo and Samuel Hym, review by Miod Vallat and Xavier Leroy) - + - [#12814](https://github.com/ocaml/ocaml/issues/12814): More detailed failure messages from `input_value` and `Marshal.from_*` (Xavier Leroy, review by Stephen Dolan and Anil Madhavapeddy) - - - [#12815](https://github.com/ocaml/ocaml/issues/12815): Correctly format multiline locations in exception backtraces in the compiler driver's + + - [#12815](https://github.com/ocaml/ocaml/issues/12815): Correctly format multiline locations in exception backtraces in the compiler driver's style. (David Allsopp, review by Gabriel Scherer) - + - [#12773](https://github.com/ocaml/ocaml/issues/12773), [#12830](https://github.com/ocaml/ocaml/issues/12830), [#12834](https://github.com/ocaml/ocaml/issues/12834): Rewrite `caml_c_thread_(un)register` to fix various bugs. (Guillaume Munch-Maccagnoni, reported by Miod Vallat, suggested by Hari Hara Naveen S, reviewed by Fabrice Buoro, Gabriel Scherer, and Miod Vallat) - + - [#12876](https://github.com/ocaml/ocaml/issues/12876): Port ThreadSanitizer support to Linux on POWER (Miod Vallat, review by Tim McGilchrist) - + - [#12886](https://github.com/ocaml/ocaml/issues/12886): Reinitialise I/O mutexes after fork (Max Slater, review by Guillaume Munch-Maccagnoni and Xavier Leroy) - + - [#12907](https://github.com/ocaml/ocaml/issues/12907): Port ThreadSanitizer support to Linux on RiscV (Miod Vallat, review by Nicolás Ojeda Bär and Fabrice Buoro) - + - [#12915](https://github.com/ocaml/ocaml/issues/12915): Port ThreadSanitizer support to Linux on s390x (Miod Vallat, review by Tim McGilchrist) - + - [#12934](https://github.com/ocaml/ocaml/issues/12934): Fix data races between marking and sweeping functions (Olivier Nicole, suggested by Stephen Dolan, review by Gabriel Scherer, Miod Vallat, and Damien Doligez) - + ### Language Features: - + - [#12295](https://github.com/ocaml/ocaml/issues/12295), [#12568](https://github.com/ocaml/ocaml/issues/12568): Give `while true` a polymorphic type, similarly to `assert false` (Jeremy Yallop, review by Nicolás Ojeda Bär and Gabriel Scherer, suggestion by Rodolphe Lepigre and John Whitington) - + - [#12044](https://github.com/ocaml/ocaml/issues/12044): Add local module open syntax for types. ``` module A = struct @@ -228,23 +228,23 @@ changelog: | type r = unit type s = string end - + type example = A.(t * r * s) ``` (Alistair O'Brien, review by Gabriel Scherer, Nicolás Ojeda Bär, and Florian Angeletti) - + - [#11252](https://github.com/ocaml/ocaml/issues/11252), RFC 27: Support raw identifier syntax `\#foo` (Stephen Dolan, review by David Allsopp, Gabriel Scherer, and Olivier Nicole) - - + + - [#12315](https://github.com/ocaml/ocaml/issues/12315): Use type annotations from arguments in `let rec` (Stephen Dolan, review by Gabriel Scherer) - + - [#12375](https://github.com/ocaml/ocaml/issues/12375): Allow use of [@untagged] for all immediate types like `char`, `bool`, and `variant` with only constant constructors. (Christophe Raffalli, review by Gabriel Scherer) - + * (*Breaking Change*) [#12502](https://github.com/ocaml/ocaml/issues/12502): The compiler now normalises the newline sequence `\r\n` to a single `\n` character during lexing to guarantee that the semantics of newlines in string literals are not modified by Windows tools @@ -253,148 +253,148 @@ changelog: | gives more robust semantics to newlines in string literals. (Gabriel Scherer and Damien Doligez, review by Daniel Bünzli, David Allsopp, Andreas Rossberg, Xavier Leroy, report by Andreas Rossberg) - + ### Standard Library: - + - [#11563](https://github.com/ocaml/ocaml/issues/11563): Add the Dynarray module to the `stdlib`. Dynamic arrays are arrays whose length can be changed by adding or removing elements at the end, similar to 'vectors' in C++ or Rust. (Gabriel Scherer, Simon Cruanes, and Florian Angeletti, review by Daniel Bünzli, Guillaume Munch-Maccagnoni, Clément Allain, Damien Doligez, Wiktor Kuchta, and Pieter Goetschalckx) - - + + - [#12716](https://github.com/ocaml/ocaml/issues/12716): Add `Format.pp_print_nothing` function. (Léo Andrès, review by Gabriel Scherer and Nicolás Ojeda Bär) - + * (*Breaking Change*) [#6732](https://github.com/ocaml/ocaml/issues/6732), [#12423](https://github.com/ocaml/ocaml/issues/12423): Make `Buffer.add_substitute` surjective and fix its documentation. (Damien Doligez, review by Antonin Décimo) - + * (*Breaking Change*) [#10775](https://github.com/ocaml/ocaml/issues/10775), [#12499](https://github.com/ocaml/ocaml/issues/12499): Half-precision, floating-point elements in Bigarray. (Anton Yabchinskiy, review by Xavier Leroy and Nicolás Ojeda Bär) - + - [#11517](https://github.com/ocaml/ocaml/issues/11517), [#12477](https://github.com/ocaml/ocaml/issues/12477): Expose `pp_infinity` in interface of the format module and check that margin is less than `pp_infinity` when setting or checking geometry. (Janith Petangoda, reported by Simmo Saan, reviewed by Florian Angeletti, Simmo Saan, Josh Berdine, and Gabriel Scherer) - + - [#12217](https://github.com/ocaml/ocaml/issues/12217): Add `Array.shuffle`. (Daniel Bünzli, review by Nicolás Ojeda Bär, David Allsopp, and Alain Frisch) - + - [#12212](https://github.com/ocaml/ocaml/issues/12212): Add cache-aligned constructor for atomics. The patch ensures that all allocations (of the right size) in the shared heap are aligned. (Bartosz Modelski with Gabriel Scherer, Guillaume Munch-Maccagnoni, Xavier Leroy, review by Alain Frisch, Anil Madhavapeddy, Gabriel Scherer, Guillaume Munch-Maccagnoni, KC Sivaramakrishnan, Stefan Muenzel, Xavier Leroy) - + - [#12307](https://github.com/ocaml/ocaml/issues/12307): Add BLAKE2b hashing and an MD5 submodule to the Digest module. (Xavier Leroy, review by Olivier Nicole, Gabriel Scherer, Wiktor Kuchta, Daniel Bünzli, David Allsopp) - + - [#12365](https://github.com/ocaml/ocaml/issues/12365): Add `In_channel.input_bigarray`, `In_channel.really_input_bigarray`, `Out_channel.output_bigarray`, `Unix.read_bigarray`, `Unix.write_bigarray`, `Unix.single_write_bigarray`. (Nicolás Ojeda Bär, review by Jeremy Yallop, Xavier Leroy, Gabriel Scherer, David Allsopp) - + - [#12455](https://github.com/ocaml/ocaml/issues/12455): Add `Array.init_matrix`, `Float.Array.make_matrix`, `Float.Array.init_matrix`. (Glen Mével, review by Xavier Leroy, Gabriel Scherer, Jeremy Yallop, Nicolas Ojeda Bar) - + * (*Breaking Change*) [#12455](https://github.com/ocaml/ocaml/issues/12455): `Array.make_matrix dimx dimy f` now raises `Invalid_argument` when `dimx = 0 && dimy < 0`. This was already specified but not enforced. (Glen Mével, report by Jeremy Yallop, review by Nicolas Ojeda Bar) - + - [#12459](https://github.com/ocaml/ocaml/issues/12459): Add `Random.int_in_range`, `Random.int32_in_range`, `Random.int64_in_range`, `Random.nativeint_in_range`, and their counterpart in `Random.State`. (Glen Mével and Xavier Leroy, review by Gabriel Scherer, Xavier Leroy, Florian Angeletti) - + - [#12459](https://github.com/ocaml/ocaml/issues/12459): `Random`: Restore compatibility between 32-bit integers (JavaScript) and 63-bit integers (64-bit OCaml). For `Random.full_int` this was guaranteed in 4.14 but wrongly removed in 5.0. (Xavier Leroy, review by Glen Mével) - + - [#12511](https://github.com/ocaml/ocaml/issues/12511): Minor performance improvements and cleanups in the implementation of modules Int32, Int64, and Nativeint (Xavier Leroy, review by Gabriel Scherer and Daniel Bünzli) - + - [#12558](https://github.com/ocaml/ocaml/issues/12558): Adapt GC alarms for Multicore and fix their documentation. (Guillaume Munch-Maccagnoni, review by KC Sivaramakrishnan and Gabriel Scherer) - + - [#12625](https://github.com/ocaml/ocaml/issues/12625): Remove the Closure module from Obj (Vincent Laviron, review by Xavier Leroy) - + - [#12758](https://github.com/ocaml/ocaml/issues/12758), [#12998](https://github.com/ocaml/ocaml/issues/12998): Remove the `Marshal.Compression` flag to the `Marshal.to_*` functions. The compilers are still able to use ZSTD compression for compilation artefacts. This is a forward port and clean-up of the emergency fix that was introduced in OCaml 5.1.1 by [#12734](https://github.com/ocaml/ocaml/issues/12734). (Xavier Leroy, review by Damien Doligez) - + - [#12784](https://github.com/ocaml/ocaml/issues/12784): Fix computation of minor-heap allocation in `Gc.counters()` and `Gc.allocated_bytes()`. (Nick Barnes, review by Gabriel Scherer) - + - [#12770](https://github.com/ocaml/ocaml/issues/12770): Add `Fun.compose`. (Justin Frank, review by Nicolás Ojeda Bär, Daniel Bünzli, and Jeremy Yallop) - + - [#12845](https://github.com/ocaml/ocaml/issues/12845): Add `{In,Out}_channel.is_binary_mode` as the dual of `set_binary_mode`. This function was previously only available in the internal C API. (David Allsopp, review by Nicolás Ojeda Bär and Xavier Leroy) - + ### Type System: - + - [#12313](https://github.com/ocaml/ocaml/issues/12313), [#11799](https://github.com/ocaml/ocaml/issues/11799): Do not rebuild as-pattern types when a ground type annotation is given. This allows to work around problems with GADTs in as-patterns. (Jacques Garrigue, report by Leo White, review by Gabriel Scherer) - + ### Code Generation and Optimisations: - + - [#11239](https://github.com/ocaml/ocaml/issues/11239): On x86-64 and RISC-V, reduce alignment of OCaml stacks from 16 to 8. This reduces stack usage. It's only C stacks that require 16-alignment. (Xavier Leroy, review by Gabriel Scherer and Stephen Dolan) - + - [#12311](https://github.com/ocaml/ocaml/issues/12311): On POWER, 32-bit FP numbers stored in memory (e.g., in Bigarrays) were not correctly rounded sometimes. (Xavier Leroy, review by Anil Madhavapeddy and Tim McGilchrist) - + - [#12551](https://github.com/ocaml/ocaml/issues/12551), [#12608](https://github.com/ocaml/ocaml/issues/12608), [#12782](https://github.com/ocaml/ocaml/issues/12782), [#12596](https://github.com/ocaml/ocaml/issues/12596): Overhaul of recursive value compilation. Non-function recursive bindings are now forbidden from Lambda onwards, and they're compiled using a new `Value_rec_compiler` module. (Vincent Laviron and Lunia Ayanides, review by Gabriel Scherer, Stefan Muenzel and Nathanaëlle Courant) - + - [#1809](https://github.com/ocaml/ocaml/issues/1809), [#12181](https://github.com/ocaml/ocaml/issues/12181): Rewrite `compare x y op 0` to `x op y` when values are integers (Xavier Clerc, Stefan Muenzel, review by Gabriel Scherer and Vincent Laviron) - + - [#12825](https://github.com/ocaml/ocaml/issues/12825): Disable common subexpression elimination for atomic loads... again. (Gabriel Scherer, review by KC Sivaramakrishnan, Xavier Leroy and Vincent Laviron, report by Vesa Karvonen) - + ### Other Libraries: - + - [#12213](https://github.com/ocaml/ocaml/issues/12213): `Dynlink` library, improve legibility of error messages (Samuel Hym, review by Gabriel Scherer and Nicolás Ojeda Bär) - + * (*Breaking Change*) [#12686](https://github.com/ocaml/ocaml/issues/12686): `Runtime_events` library, C API: define `caml_runtime_events_{start,pause,resume}` as returning `void` instead of `value`. (Xavier Leroy, review by David Allsopp) - + ### Compiler User-Interface and Warnings: - + - [#11989](https://github.com/ocaml/ocaml/issues/11989), [#12246](https://github.com/ocaml/ocaml/issues/12246), RFC 31: New flag, `-H`, to allow for transitive dependencies without including them in the initial environment. (Chris Casinghino, François Bobot, and Gabriel Scherer, review by Leo White and Stefan Muenzel, RFC by François Bobot) - - + + * (*Breaking Change*) [#10613](https://github.com/ocaml/ocaml/issues/10613), [#12405](https://github.com/ocaml/ocaml/issues/12405): Simplify the values used for the system variable (`system:` in `ocamlopt -config` or the `Config.system` constant). In particular, s390x and ppc64 now report "linux" instead of "elf"; all variants of 32-bit ARM on Linux @@ -405,136 +405,136 @@ changelog: | instead of "linux_elf". (David Allsopp, request by Kate Deplaix, review by Sébastien Hinderer and Xavier Leroy) - + - [#12247](https://github.com/ocaml/ocaml/issues/12247): Configure: `--disable-ocamldebug` can now be used instead of `--disable-debugger` (which remains available for compatibility) (Gabriel Scherer, review by Damien Doligez and Sébastien Hinderer) - + - [#12199](https://github.com/ocaml/ocaml/issues/12199): Improve the error message for non-overriding `inherit!` (Florian Angeletti, review by Jules Aguillon) - + - [#12210](https://github.com/ocaml/ocaml/issues/12210): Uniform style for inline code in compiler messages (Florian Angeletti, review by Gabriel Scherer) - + * (*Breaking Change*) [#12278](https://github.com/ocaml/ocaml/issues/12278), #:12325: Remove the `OCAML_FLEXLINK` environment variable from the compiler drivers. This environment variable was previously used as part of the FlexDLL bootstrap procedure and existed solely for that purpose. Its removal greatly simplifies both the build system and testsuite machinery. (David Allsopp, review by Sébastien Hinderer) - + - [#12347](https://github.com/ocaml/ocaml/issues/12347): Error messages: always report missing polyvariant tags (Florian Angeletti, report by Tianbo Hao, review by Gabriel Scherer) - + - [#12224](https://github.com/ocaml/ocaml/issues/12224): Specialised error message when trying to apply non-functor module (e.g., `module M = Int(Int)`) (Florian Angeletti, review by Gabriel Scherer) - + - [#12451](https://github.com/ocaml/ocaml/issues/12451): Warning 53 (misplaced attributes) now works for all attributes. (Chris Casinghino, review by Florian Angeletti) - + - [#12622](https://github.com/ocaml/ocaml/issues/12622): Give hints about existential types appearing in error messages (Leo White, review by Gabriel Scherer and Florian Angeletti) - + - [#12671](https://github.com/ocaml/ocaml/issues/12671): When a class type parameter or class parameter does not match, identify which parameter in the error message, instead of saying "A type parameter" or "A parameter." (Stefan Muenzel, review by Gabriel Scherer) - + - [#12679](https://github.com/ocaml/ocaml/issues/12679): Add more detail to the error message and manual in case of invalid module type substitutions. (Stefan Muenzel, review by Gabriel Scherer and Florian Angeletti) - + - [#12750](https://github.com/ocaml/ocaml/issues/12750): Display the command executed to extract primitives in `ocamlc -verbose` (David Allsopp, review by Nicolás Ojeda Bär) - + - [#12777](https://github.com/ocaml/ocaml/issues/12777): Add details about the actual and expected method types to the method mismatch error messages (Javier Chávarri, review by Gabriel Scherer and Florian Angeletti) - + * (*Breaking Change*) [#12942](https://github.com/ocaml/ocaml/issues/12942): Fix line ordering in some module inclusion error messages (Nick Roberts, review by Florian Angeletti, report by Carl Eastlund) - + ### Manual and Documentation: - + - [#12338](https://github.com/ocaml/ocaml/issues/12338): Clarification of the documentation of process related function in the Unix module regarding the first element of arguments and shell's PID (Christophe Raffalli, review by Florian Angeletti) - + - [#12473](https://github.com/ocaml/ocaml/issues/12473): Document in `runtime/memory.c` our current understanding of accesses to the OCaml heap from the C runtime code -- the problem of hybrid programs mixing two memory models (Gabriel Scherer and Guillaume Munch-Maccagnoni, review by Olivier Nicole and Xavier Leroy) - + - [#12456](https://github.com/ocaml/ocaml/issues/12456): Document the incompatibility between effects, on one hand, and `caml_callback` and asynchronous callbacks (signal handlers, finalisers, memprof callbacks...), on the other (Guillaume Munch-Maccagnoni, review by KC Sivaramakrishnan) - + - [#12694](https://github.com/ocaml/ocaml/issues/12694): Document in `runtime/tsan.c` the TSan instrumentation choices and the consequences with regard to the memory model (Olivier Nicole, review by Miod Vallat, Gabriel Scherer, Guillaume Munch-Maccagnoni and Fabrice Buoro) - + - [#12802](https://github.com/ocaml/ocaml/issues/12802): Add manual chapter about ThreadSanitizer support (Olivier Nicole, review by Miod Vallat, Sebastien Hinderer, Fabrice Buoro, Gabriel Scherer and KC Sivaramakrishnan) - + - [#12819](https://github.com/ocaml/ocaml/issues/12819): Clarify which runtime interactions are allowed in custom ops (Basile Clément, review by Guillaume Munch-Maccagnoni and Xavier Leroy) - + - [#12840](https://github.com/ocaml/ocaml/issues/12840): Manual: update runtime tracing chapter for custom events (e.g., [#12335](https://github.com/ocaml/ocaml/issues/12335)) (Lucas Pluvinage, Sadiq Jaffer and Olivier Nicole, review by Gabriel Scherer, David Allsopp, Tim McGilchrist, and Thomas Leonard) - + - [#13066](https://github.com/ocaml/ocaml/issues/13066): Update `OCAMLRUNPARAM` documentation for the stack size parameter `l` (Florian Angeletti, review by Nicolás Ojeda Bär, Tim McGilchrist, and Miod Vallat) - + - [#13078](https://github.com/ocaml/ocaml/issues/13078): Update Format tutorial on structural boxes to mention alignment questions (Edwin Török, review by Florian Angeletti) - + - [#13092](https://github.com/ocaml/ocaml/issues/13092): Document the existence of the `[@@poll error]` built-in attribute (Florian Angeletti, review by Gabriel Scherer) - + ### Tools: - + - [#12340](https://github.com/ocaml/ocaml/issues/12340): `testsuite`: collect known issues with current `-short-paths` implementation for existential types (Florian Angeletti, Samuel Hym, review by Florian Angeletti and Thomas Refis) - + - [#12147](https://github.com/ocaml/ocaml/issues/12147): `ocamllex`: allow carriage returns at the end-of-line directives (SeungCheol Jung, review by Nicolás Ojeda Bär) - + - [#12260](https://github.com/ocaml/ocaml/issues/12260): Fix `invalid_argument` on some external or module aliases in `ocamlnat` (Fabian Hemmer, review by Vincent Laviron) - + - [#12185](https://github.com/ocaml/ocaml/issues/12185): New script language for `ocamltest` (Damien Doligez with Florian Angeletti, Sébastien Hinderer, Gabriel Scherer, review by Sébastien Hinderer and Gabriel Scherer) - + - [#12371](https://github.com/ocaml/ocaml/issues/12371): `ocamltest`: fix recursive expansion of variables (Antonin Décimo, Damien Doligez, review by Sébastien Hinderer, Damien Doligez, Gabriel Scherer, and Xavier Leroy) - + * (*Breaking Change*) [#12497](https://github.com/ocaml/ocaml/issues/12497), [#12613](https://github.com/ocaml/ocaml/issues/12613): Make `ocamlc/ocamlopt` fail with an error when no input files are specified to build an executable (Antonin Décimo, review by Sébastien Hinderer) - + - [#12576](https://github.com/ocaml/ocaml/issues/12576): `ocamldep `: various refactors (Antonin Décimo, review by Florian Angeletti, Gabriel Scherer, and Léo Andrès) - + - [#12615](https://github.com/ocaml/ocaml/issues/12615): `ocamldoc`: get rid of the `odoc_literate` and `odoc_todo` generators (Sébaistien Hinderer, review by Gabriel Scherer and Florian Angeletti) - + - [#12624](https://github.com/ocaml/ocaml/issues/12624): Use `$XDG_CONFIG_DIRS` in addition to `$XDG_CONFIG_HOME` when searching for `init.ml`, and use this to extend `init.ml` support to the toplevel when running on Windows. (David Allsopp, report by Jonah Beckford, review by Nicolás Ojeda Bär and Antonin Décimo) - + - [#12688](https://github.com/ocaml/ocaml/issues/12688): Setting the `env` variable `NO_COLOR` with an empty value no longer has effects. Previously, setting `NO_COLOR` with any value, including the empty value, would disable colours (unless `OCAML_COLOR` is also set). @@ -542,195 +542,195 @@ changelog: | to disable colours. This reflects a specification clarification/change from the upstream website at https://no-color.org. (Favonia, review by Gabriel Scherer) - + - [#12744](https://github.com/ocaml/ocaml/issues/12744): `ocamltest`: run tests in recursive subdirs more eagerly (Nick Roberts, review by Nicolás Ojeda Bär) - + - [#12901](https://github.com/ocaml/ocaml/issues/12901), 12908: `ocamllex`: add overflow checks to prevent generating incorrect lexers; use unsigned numbers in the table encoding when possible (Vincent Laviron, report by Edwin Török, review by Xavier Leroy) - + ### Internal/`compiler-libs` Changes: - + - [#12508](https://github.com/ocaml/ocaml/issues/12508) : Add compiler-side support for project-wide occurrences in Merlin by generating index tables of all identifier occurrences. This extra data in `.cmt` files is only added when the new flag `-bin-annot-occurrences` is passed. (Ulysse Gérard, Nathanaëlle Courant, suggestions by Gabriel Scherer and Thomas Refis, review by Florian Angeletti, Gabriel Scherer, and Thomas Refis) - + - [#12236](https://github.com/ocaml/ocaml/issues/12236), [#12386](https://github.com/ocaml/ocaml/issues/12386), [#12391](https://github.com/ocaml/ocaml/issues/12391), [#12496](https://github.com/ocaml/ocaml/issues/12496), [#12673](https://github.com/ocaml/ocaml/issues/12673): Use syntax as sole determiner of arity. This changes function arity to be based solely on the source program's parsetree. Previously, the heuristic for arity had more subtle heuristics that involved type information about patterns. Function arity is important because it determines when a pattern match's effects run and is an input into the fast path for function application. - + This change affects tooling; it changes the function constructs in parsetree and typedtree. - + See https://github.com/ocaml/RFCs/pull/32 for the original RFC. - + (Nick Roberts; review by Richard Eisenberg, Leo White, and Gabriel Scherer; RFC by Stephen Dolan) - - + + - [#12639](https://github.com/ocaml/ocaml/issues/12639): Parsing: attach a location to the RHS of `Ptyp_alias` and improve the 'alias type mismatch' error message. (Jules Aguillon, review by Florian Angeletti) - + - [#12447](https://github.com/ocaml/ocaml/issues/12447): Remove 32-bit targets from `X86_proc.system` (Masanori Ogino, review by David Allsopp) - + - [#12216](https://github.com/ocaml/ocaml/issues/12216), [#12248](https://github.com/ocaml/ocaml/issues/12248): Prevent reordering of atomic loads during instruction scheduling. This is for reference, as instruction scheduling is currently unused in OCaml 5. (Xavier Leroy, report by Luc Maranget and KC Sivaramakrishnan, review by Nicolás Ojeda Bär) - + - [#12025](https://github.com/ocaml/ocaml/issues/12025): Split `Typecore.unify_pat_types` into two in order to avoid unnecessary references to the environment in `type_pat` (Jacques Garrigue and Takafumi Saikawa, review by Gabriel Scherer) - + - [#12031](https://github.com/ocaml/ocaml/issues/12031): Use dedicated types to represent names of compilation units and predefined exceptions in CMO files. (Sébastien Hinderer, review by Florian Angeletti, Thomas Refis, Gabriel Scherer, Vincent Laviron, Pierre Chambart, Luke Maurer, Hugo Heuzard, Xavier Leroy, and Damien Doligez) - + - [#12109](https://github.com/ocaml/ocaml/issues/12109): Pack parameters to unification in `unification_environment` (Takafumi Saikawa and Jacques Garrigue, review by Richard Eisenberg) - + - [#12331](https://github.com/ocaml/ocaml/issues/12331), [#12361](https://github.com/ocaml/ocaml/issues/12361): Pack the unification data for pattern checking in Typecore (Takafumi Saikawa and Jacques Garrigue, review by Gabriel Scherer, Thomas Refis, and Florian Angeletti) - + - [#12229](https://github.com/ocaml/ocaml/issues/12229): Remove global mutable state for typechecking patterns in Typecore in favor of local mutable state. (Nick Roberts, review by Takafumi Saikawa) - + - [#12542](https://github.com/ocaml/ocaml/issues/12542): Minor bugfix to [#12236](https://github.com/ocaml/ocaml/issues/12236): restore dropped call to `instance` (Nick Roberts, review by Jacques Garrigue) - + - [#12242](https://github.com/ocaml/ocaml/issues/12242): Move the computation of stack frame parameters to a separate `Stackframe` module, and save the parameters in the results of the `Linearize` pass. (Xavier Leroy, review by KC Sivaramakrishnan and Mark Shinwell) - + - [#12442](https://github.com/ocaml/ocaml/issues/12442): Document jump summaries in the pattern-matching compiler (Gabriel Scherer and Thomas Refis, review by Florian Angeletti and Vincent Laviron) - + - [#12446](https://github.com/ocaml/ocaml/issues/12446), [#12792](https://github.com/ocaml/ocaml/issues/12792): Remove the hooks machinery around channel locking in `runtime/io.c` (Gabriel Scherer, review by Xavier Leroy) - + - [#12389](https://github.com/ocaml/ocaml/issues/12389), [#12544](https://github.com/ocaml/ocaml/issues/12544), [#12984](https://github.com/ocaml/ocaml/issues/12984), [#12987](https://github.com/ocaml/ocaml/issues/12987): Centralise the handling of metadata for compilation units and artifacts in preparation to improve Unicode support for OCaml source files. (Florian Angeletti, review by Vincent Laviron and Gabriel Scherer) - + - [#12532](https://github.com/ocaml/ocaml/issues/12532), [#12553](https://github.com/ocaml/ocaml/issues/12553): Improve readability of the pattern-matching debug output (Gabriel Scherer, review by Thomas Refis) - + - [#12537](https://github.com/ocaml/ocaml/issues/12537): Use C11/C++11 standard static assertion (Antonin Décimo, review by Sebastien Hinderer, Xavier Leroy, and KC Sivaramakrishnan) - + - [#12169](https://github.com/ocaml/ocaml/issues/12169): Runtime: document and enforce naming conventions around STW sections (Gabriel Scherer, review by Enguerrand Decorne, Miod Vallat, B. Szilvasy and Nick Barnes, report by KC Sivaramakrishnan) - + - [#12669](https://github.com/ocaml/ocaml/issues/12669) : Clean up some global state handling in schedgen (Stefan Muenzel, review by Miod Vallat and Gabriel Scherer) - + - [#12640](https://github.com/ocaml/ocaml/issues/12640): Make the module separator used in symbol names configurable (Miod Vallat, review by Hugo Heuzard and Xavier Leroy) - + - [#12691](https://github.com/ocaml/ocaml/issues/12691) : Clean up `Ctype.expand_abbrev_gen` and rename `Env.add_local_type` to `add_local_constraint` (Takafumi Saikawa and Jacques Garrigue, review by Florian Angeletti) - + - [#12786](https://github.com/ocaml/ocaml/issues/12786) : Clean up the algorithm of `Ctype.limited_generalize` (Takafumi Saikawa and Jacques Garrigue, review by Gabriel Scherer) - + - [#10691](https://github.com/ocaml/ocaml/issues/10691): `Ast_mapper`, `Ast_iterator`: add functions directive_argument, `toplevel_directive`, and `toplevel_phrase` (Guillaume Petiot, review by Gabriel Scherer and Kate Deplaix) - + - [#12764](https://github.com/ocaml/ocaml/issues/12764): Move all installable headers in `caml/` subdirectories. (Antonin Décimo, review by Gabriel Scherer and David Allsopp) - + - [#12914](https://github.com/ocaml/ocaml/issues/12914): Slightly change the s390x assembly dialect in order to build with Clang's integrated assembler (Miod Vallat, review by Gabriel Scherer) - + - [#13001](https://github.com/ocaml/ocaml/issues/13001): Do not `read_back` entire shapes to get aliases' UIDs when building the usages index (Ulysse Gérard, review by Gabriel Scherer and Nathanaëlle Courant) - + ### Build System: - + - [#12198](https://github.com/ocaml/ocaml/issues/12198), [#12321](https://github.com/ocaml/ocaml/issues/12321), [#12586](https://github.com/ocaml/ocaml/issues/12586), [#12616](https://github.com/ocaml/ocaml/issues/12616), [#12706](https://github.com/ocaml/ocaml/issues/12706), [#13048](https://github.com/ocaml/ocaml/issues/13048): Continue the merge of the sub-Makefiles into the root Makefile started with [#11243](https://github.com/ocaml/ocaml/issues/11243), [#11248](https://github.com/ocaml/ocaml/issues/11248), [#11268](https://github.com/ocaml/ocaml/issues/11268), [#11420](https://github.com/ocaml/ocaml/issues/11420) and [#11675](https://github.com/ocaml/ocaml/issues/11675). (Sébastien Hinderer, review by David Allsopp and Florian Angeletti) - + - [#12569](https://github.com/ocaml/ocaml/issues/12569), [#12570](https://github.com/ocaml/ocaml/issues/12570): Remove `otherlibraries` as a prerequisite for `runtop`; use `runtop-with-otherlibs` to use a library from `otherlibs/` (Gabriel Scherer, review by Sébastien Hinderer, suggestion by David Allsopp) - + - [#12652](https://github.com/ocaml/ocaml/issues/12652): Make magic numbers easier to bump and duplicate (Sébastien Hinderer, review by Antonin Décimo, David Allsopp and Florian Angeletti) - + * (*Breaking Change*) [#12751](https://github.com/ocaml/ocaml/issues/12751): `--with-target-bindir` configure option implemented. This option refers to the location of the runtime binaries on the target system for a cross-compiler and is embedded in executables produced by `ocamlc`. It does not affect the bytecode executables installed as part of the build. The old mechanism `make TARGET_BINDIR=..` no longer works. (David Allsopp, review by Damien Doligez, Xavier Leroy, and Olivier Nicole) - + - [#12768](https://github.com/ocaml/ocaml/issues/12768), [#13030](https://github.com/ocaml/ocaml/issues/13030): Detect MinGW-w64 coupling with GCC or LLVM, detect `clang-cl`, and fix C compiler feature detection on macOS. (Antonin Décimo, review by Miod Vallat and Sébastien Hinderer) - + ### Bug Fixes: - + - [#10652](https://github.com/ocaml/ocaml/issues/10652), [#12720](https://github.com/ocaml/ocaml/issues/12720): Fix evaluation order in presence of optional arguments (Jacques Garrigue, report by Leo White, review by Vincent Laviron) - + - [#12595](https://github.com/ocaml/ocaml/issues/12595), [#12597](https://github.com/ocaml/ocaml/issues/12597): Fix a race in `caml_clear_gc_stats_sample` (Gabriel Scherer, review by B. Szilvasy, report by B. Szilvasy) - + - [#12580](https://github.com/ocaml/ocaml/issues/12580): Fix location of alias pattern variables (Chris Casinghino, review Gabriel Scherer, report by Milo Davis) - + - [#12583](https://github.com/ocaml/ocaml/issues/12583): Add a closing event for when `EV_MAJOR_EPHE_MARK` is complete (Sudha Parimala, review by Gabriel Scherer) - + - [#12566](https://github.com/ocaml/ocaml/issues/12566): `caml_output_value_to_malloc` wrongly uses `caml_stat_alloc` instead of `malloc` since 4.06, breaking (in pooled mode) user code that uses `free` on the result. Symmetrically, `caml_input_value_from_malloc` should use `free`. (Gabriel Scherer, review by Xavier Leroy and Enguerrand Decorne, report by Ido Yariv) - + - [#12490](https://github.com/ocaml/ocaml/issues/12490): Unix: protect the `popen_processes` hashtable with a mutex (Gabriel Scherer, report by Olivier Nicole, review by Xavier Leroy) - + - [#11931](https://github.com/ocaml/ocaml/issues/11931): Fix tricky typing bug with type substitutions (Stephen Dolan, review by Leo White and Jacques Garrigue) - + - [#12037](https://github.com/ocaml/ocaml/issues/12037), [#12171](https://github.com/ocaml/ocaml/issues/12171): Fix `get_extern_state` potential NULL dereference (Alexander Skvortsov, report by Török Edwin, design by Gabriel Scherer, Xavier Leroy) - + - [#12635](https://github.com/ocaml/ocaml/issues/12635): Fix `get_intern_state` potential NULL dereference (Antonin Décimo, review by KC Sivaramakrishnan) - + - [#12032](https://github.com/ocaml/ocaml/issues/12032), [#12059](https://github.com/ocaml/ocaml/issues/12059): Bug fixes related to compilation of recursive definitions (Vincent Laviron, report by Victoire Noizet, review by Gabriel Scherer) - + * (*Breaking Change*) [#12145](https://github.com/ocaml/ocaml/issues/12145): Loopy constraints cause `ocamlc` to loop. Fixed by completely removing the call to `update_type` in `Typedecl.transl_type_decl`, as the expansion is already checked by @@ -739,163 +739,163 @@ changelog: | unbound type variables and some constraints unrelated to the concrete type to be ignored (see tests/typing-misc/constraints.ml). (Jacques Garrigue, report by Richard Eisenberg, review by Leo White) - + - [#12207](https://github.com/ocaml/ocaml/issues/12207), [#12222](https://github.com/ocaml/ocaml/issues/12222): Make closure computation linear in the number of recursive functions instead of quadratic (Vincent Laviron, report by François Pottier, review by Nathanaëlle Courant and Gabriel Scherer) - + - [#11040](https://github.com/ocaml/ocaml/issues/11040), [#12591](https://github.com/ocaml/ocaml/issues/12591): Fix a data race in `major_gc.c` (Gabriel Scherer, review by Guillaume Munch-Maccagnoni and KC Sivaramakrishnan, report by Sadiq Jaffer) - + - [#12238](https://github.com/ocaml/ocaml/issues/12238), [#12403](https://github.com/ocaml/ocaml/issues/12403), [#12698](https://github.com/ocaml/ocaml/issues/12698): Read input files in one go to avoid source reprinting issues (Gabriel Scherer, report by Mike Spivey and Vincent Laviron, review by Nicolás Ojeda Bär, Xavier Leroy and Jeremy Yallop) - + - [#12334](https://github.com/ocaml/ocaml/issues/12334), [#12368](https://github.com/ocaml/ocaml/issues/12368): Bad error message with mutually recursive abbreviations (Jacques Garrigue, report by Richard Eisenberg, review by Gabriel Scherer and Richard Eisenberg) - + - [#12401](https://github.com/ocaml/ocaml/issues/12401): `seek_in` and `seek_out` sometimes returned normally when given negative offsets, instead of failing. Now both functions should consistently raise `Sys_error` in this case. (Nicolás Ojeda Bär, review by Gabriel Scherer) - + - [#12267](https://github.com/ocaml/ocaml/issues/12267): Fix stack alignment computation (Miod Vallat, report by Jan Midtgaard, review by Gabriel Scherer) - + - [#12395](https://github.com/ocaml/ocaml/issues/12395), [#12404](https://github.com/ocaml/ocaml/issues/12404): Fix thread-unsafety in the fallback implementation of `Unix.create_process` (the one used when `posix_spawnp` is unavailable) (Xavier Leroy, report by Chris Vine, review by Nicolás Ojeda Bär) - + - [#12949](https://github.com/ocaml/ocaml/issues/12949): Open shadowing mistriggers (Gabriel Scherer, review by Florian Angeletti, report by Andreas Rossberg) - + - [#12526](https://github.com/ocaml/ocaml/issues/12526): Honor `ocaml.inline always` attribute on functions with optional arguments and default values in the Closure backend (Alain Frisch, review by Vincent Laviron) - + - [#12677](https://github.com/ocaml/ocaml/issues/12677), [#12889](https://github.com/ocaml/ocaml/issues/12889): Make `Domain.DLS` thread-safe (Gabriel Scherer, review by Olivier Nicole and Damien Doligez, report by Vesa Karvonen) - + - [#12561](https://github.com/ocaml/ocaml/issues/12561): Fix crash when combining TSan and frame-pointers (Fabrice Buoro and Olivier Nicole, report by Jan Midtgaard, review by Miod Vallat and Gabriel Scherer) - + - [#12482](https://github.com/ocaml/ocaml/issues/12482): Rework bounds checking code in the POWER backend (Miod Vallat and Xavier Leroy, report by Jan Midtgaard, review by KC Sivaramakrishnan) - + - [#12528](https://github.com/ocaml/ocaml/issues/12528), [#12703](https://github.com/ocaml/ocaml/issues/12703): Avoid pointer arithmetic overflow in `Tag_val` macro (very likely harmless, but can trigger alarms) (Xavier Leroy, report by Sam Goldman, review by Guillaume Munch-Maccagnoni) - + - [#12593](https://github.com/ocaml/ocaml/issues/12593): TSan should handle `Effect.Unhandled` correctly (Fabrice Buoro and Olivier Nicole, report by Jan Midtgaard and Miod Vallat, review by Gabriel Scherer) - + - [#12684](https://github.com/ocaml/ocaml/issues/12684): Fix locations filename in AST produced by the `-pp` option (Gabriel Scherer, review by Florian Angeletti) - + - [#12714](https://github.com/ocaml/ocaml/issues/12714): Check whether macros are defined before using them to ensure that the headers can always be used in code which turns on `-Wundef` (or equivalent). (Antonin Décimo, review by Miod Vallat, Gabriel Scherer, Xavier Leroy, and David Allsopp) - + - [#12726](https://github.com/ocaml/ocaml/issues/12726): Fix segmentation fault under Windows when executing a bytecode file if the runtime (`ocamlrun.exe`) cannot be found. (Vadim Zborovskii, Nicolás Ojeda Bär, report by Vadim Zborovskii, review by David Allsopp) - + - [#12727](https://github.com/ocaml/ocaml/issues/12727), [#12730](https://github.com/ocaml/ocaml/issues/12730): Fix bug with value `let-rec` and labelled applications (Vincent Laviron, review by Gabriel Scherer) - + * (*Breaking Change*) [#12751](https://github.com/ocaml/ocaml/issues/12751): Always keep within the 128 character limit for shebang lines. Previous fix in [#8622](https://github.com/ocaml/ocaml/issues/8622) handled building the compiler with a long prefix. This patch extends this to the bytecode executables emitted by that compiler. (David Allsopp, review by Damien Doligez, Xavier Leroy, and Olivier Nicole) - + - [#12755](https://github.com/ocaml/ocaml/issues/12755): Fix data race on global pools arrays of `pool_freelist` (Fabrice Buoro and Olivier Nicole, review by Gabriel Scherer) - + - [#12796](https://github.com/ocaml/ocaml/issues/12796), [#12801](https://github.com/ocaml/ocaml/issues/12801): Fix memory corruption in `caml_unix_alloc_sockaddr` (Thomas Leonard, review by Nicolás Ojeda Bär) - + - [#12737](https://github.com/ocaml/ocaml/issues/12737): Fix data races in `minor_gc.c` and `caml_natdynlink_open` (Olivier Nicole, review by Stefan Muenzel, Miod Vallat, Guillaume Munch-Maccagnoni, Gabriel Scherer, and Xavier Leroy) - + - [#12831](https://github.com/ocaml/ocaml/issues/12831): Fix call to `caml_call_realloc_stack` for s390x in PIC mode (Vincent Laviron, report by Jerry James, review by Miod Vallat) - + * (*Breaking Change*) [#12837](https://github.com/ocaml/ocaml/issues/12837): Show non-generalisable type parameters in type definitions Changes type of type parameters in `outcometree.mli`. (Jacques Garrigue, review by Richard Eisenberg) - + - [#12897](https://github.com/ocaml/ocaml/issues/12897): Fix locking bugs in `Runtime_events` (Gabriel Scherer and Thomas Leonard, review by Olivier Nicole, Vincent Laviron, and Damien Doligez, report by Thomas Leonard) - + - [#12851](https://github.com/ocaml/ocaml/issues/12851): Fix race between runtime events teardown and event emission (Olivier Nicole, review by Miod Vallat and Gabriel Scherer) - + - [#12860](https://github.com/ocaml/ocaml/issues/12860): Fix an assertion that wasn't taking into account the possibility of an ephemeron pointing at static data (Mark Shinwell, review by Gabriel Scherer and KC Sivaramakrishnan) - + - [#12861](https://github.com/ocaml/ocaml/issues/12861): Fix a possible crash in the `threads` library (Mark Shinwell, review by Gabriel Scherer and KC Sivaramakrishnan) - + - [#11040](https://github.com/ocaml/ocaml/issues/11040), [#12894](https://github.com/ocaml/ocaml/issues/12894): Silence false data race observed between `caml_shared_try_alloc` and oldify. Introduces macros to call TSan annotations which help annotate a "happens before" relationship. (Hari Hara Naveen S and Olivier Nicole, review by Gabriel Scherer and Miod Vallat) - + - [#12958](https://github.com/ocaml/ocaml/issues/12958): Fix `tail-modulo-cons` compilation of `try-with`, `&&`, and `||` expressions. (Gabriel Scherer and Nicolás Ojeda Bär, report by Sylvain Boilard, review by Gabriel Scherer) - + - [#12919](https://github.com/ocaml/ocaml/issues/12919): Fix register corruption in `caml_callback2_asm` on s390x. (Miod Vallat, review by Gabriel Scherer) - + - [#12924](https://github.com/ocaml/ocaml/issues/12924), [#12930](https://github.com/ocaml/ocaml/issues/12930): Rework package constraint checking to improve interaction with immediacy (Chris Casinghino and Florian Angeletti, review by Florian Angeletti and Richard Eisenberg) - + - [#12969](https://github.com/ocaml/ocaml/issues/12969): Fix a data race in `caml_darken_cont` (Fabrice Buoro and Olivier Nicole, review by Gabriel Scherer and Miod Vallat) - + - [#12971](https://github.com/ocaml/ocaml/issues/12971), [#12974](https://github.com/ocaml/ocaml/issues/12974): Fix an uncaught `Ctype.Escape` exception on some invalid programs forming recursive types. (Gabriel Scherer, review by Florian Angeletti, report by Neven Villani) - + - [#13019](https://github.com/ocaml/ocaml/issues/13019): Remove linking instructions for the Unix library from `threads.cma`. (This was done for `threads.cmxa` in OCaml 3.11.) Eliminates warnings from new LLD when using `threads.cma` of duplicated libraries. (David Allsopp, review by Nicolás Ojeda Bär) - + - [#13058](https://github.com/ocaml/ocaml/issues/13058): Add TSan instrumentation to `caml_call_gc()`, since it may raise exceptions. (Fabrice Buoro, Olivier Nicole, Gabriel Scherer, and Miod Vallat) - + - [#13079](https://github.com/ocaml/ocaml/issues/13079): Save and restore frame pointer across Iextcall on ARM64 (Tim McGilchrist, review by KC Sivaramakrishnan and Miod Vallat) - + - [#13094](https://github.com/ocaml/ocaml/issues/13094): Fix undefined behavior of left-shifting a negative number (Antonin Décimo, review by Miod Vallat and Nicolás Ojeda Bär) - + - [#13130](https://github.com/ocaml/ocaml/issues/13130): Minor fixes to Pprintast for raw identifiers and local module open syntax for types (Chet Murthy, review by Gabriel Scherer) - + --- We have the pleasure of celebrating Inge Lehmann's birthday by announcing the @@ -907,7 +907,7 @@ Some of the highlights in OCaml 5.2.0 are: - Thread sanitiser support - New Dynarray module - New `-H` flag for hidden include directories -- Project-wide occurence metadata support for developer tools +- Project-wide occurrence metadata support for developer tools - Raw identifiers - Local open in type expressions diff --git a/data/changelog/ocaml/2024-11-18-ocaml-5.2.1.md b/data/changelog/releases/ocaml/2024-11-18-ocaml-5.2.1.md similarity index 100% rename from data/changelog/ocaml/2024-11-18-ocaml-5.2.1.md rename to data/changelog/releases/ocaml/2024-11-18-ocaml-5.2.1.md diff --git a/data/changelog/releases/ocaml/2025-01-08-ocaml-5.3.0.md b/data/changelog/releases/ocaml/2025-01-08-ocaml-5.3.0.md new file mode 100644 index 0000000000..28bdd231f7 --- /dev/null +++ b/data/changelog/releases/ocaml/2025-01-08-ocaml-5.3.0.md @@ -0,0 +1,811 @@ +--- +title: Release of OCaml 5.3.0 +description: Release of OCaml 5.3.0 +tags: [ocaml] +changelog: | + (Changes that can break existing programs are marked with a "*") + ### Restored backend: + + - [#12954](https://github.com/ocaml/ocaml/issues/12954): Restore the MSVC port + (David Allsopp, Antonin Décimo, Samuel Hym, and Miod Vallat, review by Nicolás + Ojeda Bär) + + - [#13093](https://github.com/ocaml/ocaml/issues/13093): Allow building the MSVC port with clang-cl. + (Antonin Décimo, review by Nicolás Ojeda Bär, Samuel Hym, + David Allsopp and Sébastien Hinderer) + + ### Language features: + + - [#12309](https://github.com/ocaml/ocaml/issues/12309), [#13158](https://github.com/ocaml/ocaml/issues/13158): Add syntax support for deep effect handlers + (Leo White, Tom Kelly, Anil Madhavapeddy, KC Sivaramakrishnan, Xavier Leroy + and Florian Angeletti, review by the same, Hugo Heuzard, and Ulysse Gérard) + + - [#11736](https://github.com/ocaml/ocaml/issues/11736), [#12664](https://github.com/ocaml/ocaml/issues/12664), [#13628](https://github.com/ocaml/ocaml/issues/13628): Support utf-8 encoded source files and latin-9 + compatible identifiers. + (Xavier Leroy and Florian Angeletti, review by Daniel Bünzli and + Jules Aguillon) + + + - [#12828](https://github.com/ocaml/ocaml/issues/12828), [#13283](https://github.com/ocaml/ocaml/issues/13283): Add short syntax for dependent functor types `(X:A) -> ...` + (Jeremy Yallop, review by Nicolás Ojeda Bär and Gabriel Scherer) + + ### Type system + + - [#11891](https://github.com/ocaml/ocaml/issues/11891), [#12507](https://github.com/ocaml/ocaml/issues/12507): Allow to name new locally abstract types in constructor type + annotations. + (Jacques Garrigue, report and review by Gabriel Scherer and Florian Angeletti) + + ### Runtime system: + + - [#11911](https://github.com/ocaml/ocaml/issues/11911), [#12923](https://github.com/ocaml/ocaml/issues/12923): Multicore statistical memory profiling. + This restores a notable OCaml 4 feature that was missing + in OCaml 5. + (Nick Barnes, review by Stephen Dolan, Jacques-Henri Jourdan + and Guillaume Munch-Maccagnoni). + + + - [#13419](https://github.com/ocaml/ocaml/issues/13419): Fix memory bugs in runtime events system. + (B. Szilvasy and Nick Barnes, review by Miod Vallat, Nick Barnes, + Tim McGilchrist, and Gabriel Scherer) + + - [#13364](https://github.com/ocaml/ocaml/issues/13364): Emit major slice counters in the runtime events. + (KC Sivaramakrishnan and Sadiq Jaffer, review by Gabriel Scherer) + + - [#13382](https://github.com/ocaml/ocaml/issues/13382): Add more documentation for Runtime_events types + (Sadiq Jaffer, review by Tim McGilchrist, Miod Vallat and KC Sivaramakrishnan) + + - [#13370](https://github.com/ocaml/ocaml/issues/13370): Fix a low-probability crash when calling Gc.counters. + (Demi Marie Obenour, review by Gabriel Scherer) + + - [#13272](https://github.com/ocaml/ocaml/issues/13272): Allow maximum number of domains to be specified as a OCAMLRUNPARAM + parameter. + (KC Sivaramakrishnan, review by Guillaume Munch-Maccagnoni, Miod Vallat, + Gabriel Scherer, David Allsopp, request by Zachary Yedidia). + + - [#12579](https://github.com/ocaml/ocaml/issues/12579): OS-based Synchronisation for Stop-the-World Sections + (B. Szilvasy, review by Miod Vallat, Nick Barnes, Olivier Nicole, + Gabriel Scherer and Damien Doligez) + + - [#12789](https://github.com/ocaml/ocaml/issues/12789): Restore caml_unregister_frametable from OCaml 4 + (Frédéric Recoules, review by Gabriel Scherer) + + - [#13003](https://github.com/ocaml/ocaml/issues/13003): new, more consistent names for array-creation C functions + (Gabriel Scherer, review by Olivier Nicole) + + - [#13013](https://github.com/ocaml/ocaml/issues/13013): introduce a `caml_result` type to supersede the + use of 'encoded exception values' in the FFI. + (Gabriel Scherer, review by Damien Doligez, + Guillaume Munch-Maccagnoni and Xavier Leroy, + suggested by Guillaume Munch-Maccagnoni) + + - [#12407](https://github.com/ocaml/ocaml/issues/12407), [#13226](https://github.com/ocaml/ocaml/issues/13226): Resource-handling improvements: add + exception-returning variants for all exception-raising functions in + `caml/fail.h`, for the purpose of cleaning-up state and resources + before raising. + (Guillaume Munch-Maccagnoni, review by Damien Doligez, Xavier Leroy + and Gabriel Scherer) + + - [#13086](https://github.com/ocaml/ocaml/issues/13086): Avoid spurious major GC slices. + (Damien Doligez, report by Stephen Dolan, review by Gabriel Scherer + and Stephen Dolan) + + - [#11779](https://github.com/ocaml/ocaml/issues/11779), [#13117](https://github.com/ocaml/ocaml/issues/13117): Improve logic for fiber stack alignment. + (Miod Vallat, report by Damien Doligez, review by Gabriel Scherer) + + - [#12839](https://github.com/ocaml/ocaml/issues/12839): Remove ATOMIC_UINTNAT_INIT from camlatomic.h (as part of a larger + cleanup of camlatomic.h) + (David Allsopp, review by Antonin Décimo, Sébastien Hinderer, Samuel Hym, + Guillaume Munch-Maccagnoni and Miod Vallat) + + - [#13163](https://github.com/ocaml/ocaml/issues/13163): Enable frame pointers on macOS x86_64 + (Tim McGilchrist, review by Sébastien Hinderer and Fabrice Buoro) + + - [#12951](https://github.com/ocaml/ocaml/issues/12951): Constify constructors and flags tables in C code (take 2). + Now these tables will go in the readonly segment, where they belong. + (Antonin Décimo, review by David Allsopp) + + - [#10696](https://github.com/ocaml/ocaml/issues/10696): Introduce __has_attribute and __has_c_attributes in + to test the support of specific attributes in C + code. Introduce fallthrough as a wrapper around the fallthrough + attribute. + (Antonin Décimo, review by Nicolás Ojeda Bär, Xavier Leroy, and + Gabriel Scherer) + + - [#13083](https://github.com/ocaml/ocaml/issues/13083): Use macros from limits.h to avoid signed-integer wrap-around. + Introduce CAML_{U,}INTNAT_{MIN,MAX} macros to expose {u,}intnat limits. + (Antonin Décimo, review by Nick Barnes, Xavier Leroy, Gabriel Scherer, + and Miod Vallat) + + - [#13239](https://github.com/ocaml/ocaml/issues/13239): Check whether the compiler supports the labels as values + extension to enable threaded code interpretation. + (Antonin Décimo, review by Miod Vallat) + + - [#13238](https://github.com/ocaml/ocaml/issues/13238): Enable software prefetching on x86 and x86_64 when building + with MSVC or clang-cl. + (Antonin Décimo, review by Miod Vallat) + + - [#13241](https://github.com/ocaml/ocaml/issues/13241), [#13261](https://github.com/ocaml/ocaml/issues/13261), [#13271](https://github.com/ocaml/ocaml/issues/13271): Add CFI_SIGNAL_FRAME to ARM64 and RiscV runtimes, + for the purpose of displaying backtraces correctly in GDB. + (Tim McGilchrist, review by Miod Vallat, Gabriel Scherer and + KC Sivaramakrishnan) + + - [#13139](https://github.com/ocaml/ocaml/issues/13139): Simplify CAMLalign to always use C23/C++11 alignas or C11 + _Alignas. Ensures that stat data is always aligned to the best + boundary. + (Antonin Décimo, review by Miod Vallat and Xavier Leroy) + + - [#13280](https://github.com/ocaml/ocaml/issues/13280): Check for support of compiler attributes. Allows using + compiler attributes with clang-cl. + (Antonin Décimo, review by Miod Vallat) + + - [#13243](https://github.com/ocaml/ocaml/issues/13243): Enable C compiler warnings internally when building with + clang-cl or MSVC. Provide fixes too. + (Antonin Décimo, review by Miod Vallat and Xavier Leroy) + + - [#13242](https://github.com/ocaml/ocaml/issues/13242): Define and use unreachable and trap annotation, and clean-up some + runtime assertions. + (Antonin Décimo, review by Miod Vallat, Gabriel Scherer, and David Allsopp) + + - [#13402](https://github.com/ocaml/ocaml/issues/13402), [#13512](https://github.com/ocaml/ocaml/issues/13512), [#13549](https://github.com/ocaml/ocaml/issues/13549), [#13553](https://github.com/ocaml/ocaml/issues/13553): Revise bytecode implementation of callbacks + so that it no longer produces dangling registered bytecode fragments. + (Xavier Leroy, report by Jan Midtgaard, analysis by Stephen Dolan, + review by Miod Vallat) + + - [#13407](https://github.com/ocaml/ocaml/issues/13407): Add Runtime_events.EV_EMPTY_MINOR + (Thomas Leonard) + + - [#13522](https://github.com/ocaml/ocaml/issues/13522): Confirm runtime events ring is still active after callback. + (KC Sivaramakrishnan, review by Sadiq Jaffer and Miod Vallat) + + - [#13529](https://github.com/ocaml/ocaml/issues/13529): Do not write to event ring after going out of stw participant set. + (KC Sivaramakrishnan, review by Sadiq Jaffer) + + ### Code generation and optimizations: + + - [#13014](https://github.com/ocaml/ocaml/issues/13014): Enable compile-time option -function-sections on all previously + unsupported native backends (POWER, riscv64 and s390x) + (Miod Vallat, review by Nicolás Ojeda Bär) + + - [#7241](https://github.com/ocaml/ocaml/issues/7241), [#12555](https://github.com/ocaml/ocaml/issues/12555), [#13076](https://github.com/ocaml/ocaml/issues/13076), [#13138](https://github.com/ocaml/ocaml/issues/13138), [#13338](https://github.com/ocaml/ocaml/issues/13338), [#13152](https://github.com/ocaml/ocaml/issues/13152), [#13153](https://github.com/ocaml/ocaml/issues/13153), [#13154](https://github.com/ocaml/ocaml/issues/13154): + fix a soundness bug in the pattern-matching compiler + when side-effects mutate the scrutinee during matching. + (Gabriel Scherer, review by Nick Roberts) + + - [#13341](https://github.com/ocaml/ocaml/issues/13341): a warning when the pattern-matching compiler pessimizes code + because side-effects may mutate the scrutinee during + matching. (This warning is disabled by default, as this rarely + happens and its performance impact is typically not noticeable.) + (Gabriel Scherer, review by Nick Roberts, Florian Angeletti + and David Allsopp) + + - [#13179](https://github.com/ocaml/ocaml/issues/13179): Fix evaluation of toplevel lets in classes containing + local opens + (Vincent Laviron, review by Hugo Heuzard, Nathanaëlle Courant + and Gabriel Scherer) + + - [#13543](https://github.com/ocaml/ocaml/issues/13543): Remove some String-Bytes conversion from the stdlib to behave better + with js_of_ocaml + (Hugo Heuzard, review by Gabriel Scherer) + + ### Standard library: + + - [#12885](https://github.com/ocaml/ocaml/issues/12885): move Dynarray to an unboxed representation + (Gabriel Scherer, suggestions by Vincent Laviron, + review by Olivier Nicole and Simon Cruanes, Yann Leray, Alain Frisch) + + + - [#12884](https://github.com/ocaml/ocaml/issues/12884): Add `Queue.drop` + (Léo Andrès, review by Nicolás Ojeda Bär and Gabriel Scherer) + + - [#13168](https://github.com/ocaml/ocaml/issues/13168): In Array.shuffle, clarify the code that validates the + result of the user-supplied function `rand`, and improve the + error message that is produced when this result is invalid. + (François Pottier, review by Florian Angeletti, Daniel Bünzli + and Gabriel Scherer) + + - [#12133](https://github.com/ocaml/ocaml/issues/12133): Expose support for printing substrings in Format + (Florian Angeletti, review by Daniel Bünzli, Gabriel Scherer + and Nicolás Ojeda Bär) + + - [#12869](https://github.com/ocaml/ocaml/issues/12869): Add List.take, List.drop, List.take_while and List.drop_while + (Kate Deplaix and Oscar Butler-Aldridge, review by Nicolás Ojeda Bär, + Craig Ferguson and Gabriel Scherer) + + - [#13047](https://github.com/ocaml/ocaml/issues/13047): Add Sys.poll_actions to (only) run pending runtime actions. + (Nick Barnes, review by Gabriel Scherer, Guillaume Munch-Maccagnoni, and + Vincent Laviron) + + - [#13144](https://github.com/ocaml/ocaml/issues/13144): Dynarray.{equal, compare} + (Gabriel Scherer, + review by Jeremy Yallop, Daniel Bünzli and Olivier Nicole, + request by Olivier Nicole) + + - [#13171](https://github.com/ocaml/ocaml/issues/13171): expose `Domain.self_index : unit -> int` (a somewhat-dense + indexing of currently-running domains) for advanced use-cases of + domain-indexed concurrent data structures. + (Gabriel Scherer, + review by KC Sivaramakrishnan, Miod Vallat and Nicolás Ojeda Bär, + report by Vesa Karvonen) + + - [#13197](https://github.com/ocaml/ocaml/issues/13197): Dynarray.blit, which allows to extend the destination + dynarray (0 <= dst_pos <= dst_length). + (Gabriel Scherer, report by Hazem Elmasry, + review by Olivier Nicole, Hazem Elmasry and Nicolás Ojeda Bär) + + * (*breaking change*) [#13240](https://github.com/ocaml/ocaml/issues/13240): Add Uchar.seeded_hash, Change Uchar.hash implementation. + Previously, Uchar.hash was aliased to Uchar.to_int. If you need that behavior, + change your module instantiation from eg `module HT = Hashtbl.Make(Uchar)` to + ``` + module HT = Hashtbl.Make(struct + ... + let hash = Uchar.to_int + end) + ``` + If the current implementation is desired, and you have a hashtable module `HT` + (produced with the `Make` functor) in persistent storage, use `HT.rebuild` to + ensure it doesn't break when reading from or writing to buckets. + (Hazem ElMasry, review by Gabriel Scherer and Nicolás Ojeda Bär) + + - [#13318](https://github.com/ocaml/ocaml/issues/13318): Fix regression in GC alarms, and fix them for flambda. + (Guillaume Munch-Maccagnoni, report by Benjamin Monate, review by + Vincent Laviron and Gabriel Scherer) + + - [#13296](https://github.com/ocaml/ocaml/issues/13296): Add mem, memq, find_opt, find_index, find_map and find_mapi + to Dynarray. + (Jake H, review by Gabriel Scherer and Florian Angeletti) + + ### Other libraries: + + - [#11996](https://github.com/ocaml/ocaml/issues/11996): release the dependency of dynlink on compilerlibs. + (Sébastien Hinderer and Stephen Dolan, review by Damien Doligez and + Hugo Heuzard) + + - [#13326](https://github.com/ocaml/ocaml/issues/13326): Implement Unix.O_APPEND on windows. + (Romain Beauxis, review by Miod Vallat, Gabriel Scherer and Antonin Décimo) + + ### Tools: + + - [#11716](https://github.com/ocaml/ocaml/issues/11716): ocamllex: mismatched parentheses and curly brackets are now caught + by ocamllex, instead of causing invalid OCaml code to be generated. + (Demi Marie Obenour, review by Damien Doligez and Xavier Leroy) + + - [#12904](https://github.com/ocaml/ocaml/issues/12904): Run the testsuite with ThreadSanitizer on a PR when label + `run-thread-sanitizer` is added + (Olivier Nicole, suggested by Sébastien Hinderer and David Allsopp, review by + Gabriel Scherer) + + * (*breaking change*) [#13114](https://github.com/ocaml/ocaml/issues/13114): Support ocamldebug remote debugging over IPv6 on all + platforms, and over Unix domain sockets on Windows. + (Antonin Décimo, review by Gabriel Scherer and Miod Vallat) + + - [#13136](https://github.com/ocaml/ocaml/issues/13136): Rewrite GDB extensions and macros in debugger-agnostic Python, and add + LLDB support for them. + (Nick Barnes, review by Tim McGilchrist and Gabriel Scherer) + + ### Toplevel: + + - [#12891](https://github.com/ocaml/ocaml/issues/12891): Improved styling for initial prompt + (Florian Angeletti, review by Gabriel Scherer) + + - [#13053](https://github.com/ocaml/ocaml/issues/13053): Improved display of builtin types such as `_ list` when aliased. + (Samuel Vivien, review by Florian Angeletti) + + ### Manual and documentation: + + - [#13370](https://github.com/ocaml/ocaml/issues/13370): Document that that temporary variables holding GCd pointers must + not be live across a GC. + (Demi Marie Obenour) + + - [#12298](https://github.com/ocaml/ocaml/issues/12298): Manual: emphasize that Bigarray.int refers to an OCaml integer, + which does not match the C int type. + (Edwin Török, review by Florian Angeletti) + + - [#12868](https://github.com/ocaml/ocaml/issues/12868): Manual: simplify style colours of the post-processed manual and API + HTML pages, and fix the search button icon + (Yawar Amin, review by Simon Grondin, Gabriel Scherer, and Florian Angeletti) + + - [#12949](https://github.com/ocaml/ocaml/issues/12949): document OCaml release cycles and version strings in + `release-info/introduction.md`. + (Florian Angeletti, review by Fabrice Buoro, Kate Deplaix, Damien Doligez, and + Gabriel Scherer) + + - [#12976](https://github.com/ocaml/ocaml/issues/12976): Manual: use webman//*.html and + webman//api/ for OCaml.org HTML manual generation + (Shakthi Kannan, review by Hannes Mehnert, and Florian Angeletti) + + - [#13045](https://github.com/ocaml/ocaml/issues/13045): Emphasize caution about behaviour of custom block finalizers. + (Nick Barnes) + + - [#13216](https://github.com/ocaml/ocaml/issues/13216): document the new `caml_result` type in the FFI chapter of the manual. + (Gabriel Scherer, review by Miod Vallat, Daniel Bünzli, Nick Barnes, + Guillaume Munch-Maccagnoni and Antonin Décimo) + + - [#13287](https://github.com/ocaml/ocaml/issues/13287): stdlib/sys.mli: Update documentation on Sys.opaque_identity + following [#9412](https://github.com/ocaml/ocaml/issues/9412). + (Matt Walker, review by Guillaume Munch-Maccagnoni and Vincent Laviron) + + - [#13295](https://github.com/ocaml/ocaml/issues/13295): Use syntax for deep effect handlers in the effect handlers manual + page. + (KC Sivaramakrishnan, review by Anil Madhavapeddy, Florian Angeletti and Miod + Vallat) + + - [#13424](https://github.com/ocaml/ocaml/issues/13424): Fix `Gc.quick_stat` documentation to clarify that returned fields + `live_words`, `live_blocks`, `free_words`, and `fragments` are not zero. + (Jan Midtgaard, review by Damien Doligez and KC Sivaramakrishnan) + + - [#13440](https://github.com/ocaml/ocaml/issues/13440): Update documentation of `Gc.{control,get,set}` to reflect fields + not currently supported on OCaml 5. + (Jan Midtgaard, review by Gabriel Scherer) + + - [#13469](https://github.com/ocaml/ocaml/issues/13469), [#13474](https://github.com/ocaml/ocaml/issues/13474), [#13535](https://github.com/ocaml/ocaml/issues/13535): Document that [Hashtbl.create n] creates a hash table + with a default minimal size, even if [n] is very small or negative. + (Antonin Décimo, Nick Bares, report by Nikolaus Huber and Jan Midtgaard, + review by Florian Angeletti, Anil Madhavapeddy, Gabriel Scherer, + and Miod Vallat) + + - [#13666](https://github.com/ocaml/ocaml/issues/13666): Rewrite parts of the example code around nested lists in Chapter 6 + (Polymorphism and its limitations -> Polymorphic recursion) giving the + "depth" function [in the non-polymorphically-recursive part of the example] + a much more sensible behavior; also fix a typo and some formatting. + (Frank Steffahn, review by Florian Angeletti) + + - [#13668](https://github.com/ocaml/ocaml/issues/13668): Document the basic support for unicode identifiers and the switch to + UTF-8 encoded Unicode text for OCaml source file + (Florian Angeletti, review by Nicolás Ojeda Bär and Daniel Bünzli) + + ### Compiler user-interface and warnings: + + * (*breaking change*) [#12084](https://github.com/ocaml/ocaml/issues/12084), [#13669](https://github.com/ocaml/ocaml/issues/13669), [#13673](https://github.com/ocaml/ocaml/issues/13673): Check link order when creating archive and when using + ocamlopt. + (Hugo Heuzard, review by Stefan Muenzel and Sébastien Hinderer) + + - [#12980](https://github.com/ocaml/ocaml/issues/12980): Explain type mismatch involving first-class modules by including + the module level error message + (Florian Angeletti, review by Vincent Laviron) + + - [#12985](https://github.com/ocaml/ocaml/issues/12985), [#12988](https://github.com/ocaml/ocaml/issues/12988): Better error messages for partially applied functors. + (Florian Angeletti, report by Arthur Wendling, review by Gabriel Scherer) + + - [#13034](https://github.com/ocaml/ocaml/issues/13034), [#13260](https://github.com/ocaml/ocaml/issues/13260): Better error messages for mismatched function labels + (Florian Angeletti, report by Daniel Bünzli, review by Gabriel Scherer and + Samuel Vivien) + + - [#13051](https://github.com/ocaml/ocaml/issues/13051): Add a "Syntax error" to error messages for invalid package signatures. + (Samuel Vivien, review by Gabriel Scherer) + + - [#13099](https://github.com/ocaml/ocaml/issues/13099): Fix erroneous loading of cmis for some module type errors. + (Nick Roberts, review by Florian Angeletti) + + - [#13151](https://github.com/ocaml/ocaml/issues/13151), name conflicts explanation as a footnote + (Florian Angeletti, review by Gabriel Scherer) + + - [#13228](https://github.com/ocaml/ocaml/issues/13228): Re-export Cmt2annot.{iterator,binary_part} which had become hidden + since [#11288](https://github.com/ocaml/ocaml/issues/11288) and broke ocamlbrowser. + (David Allsopp, report by Jacques Garrigue, review by Sébastien Hinderer) + + - [#13251](https://github.com/ocaml/ocaml/issues/13251): Register printer for errors in Emitaux + (Vincent Laviron, review by Miod Vallat and Florian Angeletti) + + - [#13255](https://github.com/ocaml/ocaml/issues/13255): Re-enable warning 34 for unused locally abstract types + (Nick Roberts, review by Chris Casinghino and Florian Angeletti) + + - [#12182](https://github.com/ocaml/ocaml/issues/12182): Improve the type clash error message. + For example, this message: + This expression has type ... + is changed into: + The constant "42" has type ... + (Jules Aguillon, review by Gabriel Scherer and Florian Angeletti) + + - [#13471](https://github.com/ocaml/ocaml/issues/13471): add `-keywords ` flag to define the list of keywords + recognized by the lexer, for instance `-keywords 5.2` disable the `effect` + keyword. + (Florian Angeletti, review by Gabriel Scherer) + + ### Internal/compiler-libs changes: + + - [#13286](https://github.com/ocaml/ocaml/issues/13286): Distinguish unique identifiers `Shape.Uid.t` according to their + provenance: either an implementation or an interface. + (Ulysse Gérard, review by Florian Angeletti and Leo White) + + - [#13308](https://github.com/ocaml/ocaml/issues/13308): keep track of relations between declaration in the cmt files. This is + useful information for external tools for navigation and analysis purposis. + (Ulysse Gérard, Florian Angeletti, review by Florian Angeletti and Gabriel + Scherer) + + + - [#11129](https://github.com/ocaml/ocaml/issues/11129), [#11148](https://github.com/ocaml/ocaml/issues/11148): enforce that ppxs do not produce `parsetree`s with + an empty list of universally quantified type variables + (`. int -> int` instead of `'a . int -> int'`) + (Florian Angeletti, report by Simmo Saan, review by Gabriel Scherer) + + - [#12534](https://github.com/ocaml/ocaml/issues/12534): document and refactor Matching.mk_failaction_pos + (Gabriel Scherer, review by Vincent Laviron and Nick Roberts) + + - [#13076](https://github.com/ocaml/ocaml/issues/13076): change the handling of Match_failure exits in the pattern-matching + compiler, to prepare for a complete fix for [#7241](https://github.com/ocaml/ocaml/issues/7241) + (Gabriel Scherer, review by Thomas Refis and Nick Roberts) + + - [#12896](https://github.com/ocaml/ocaml/issues/12896): Simplify the compilation of custom bytecode runtimes by explicitly + compiling the primitives file before calling the linker. Tidy-up both the + generating code and the output itself for C code being generated by the + bytecode linker in `-custom` and `-output-*` modes. + (David Allsopp, Antonin Décimo and Samuel Hym, review by Vincent Laviron) + + - [#12932](https://github.com/ocaml/ocaml/issues/12932): Remove useless code in Typecore.type_label_exp (was a fix for [#4862](https://github.com/ocaml/ocaml/issues/4862)) + (Jacques Garrigue, review by Gabriel Scherer) + + - [#12943](https://github.com/ocaml/ocaml/issues/12943): Make transient_expr.scope a bitfield, and use it to store marks. + Marks are automatically allocated, and removed when leaving their scope. + Falls back to using TransientTypeSet when marks are exhausted. + (Jacques Garrigue and Takafumi Saikawa, review by Basile Clément) + + - [#12946](https://github.com/ocaml/ocaml/issues/12946): Make generalization automatic when leaving scope. + As a result, the `Ctype.generalize*` and `Ctype.correct_levels` functions + were removed. The latter is now called `Ctype.duplicate_type`. + (Jacques Garrigue and Takafumi Saikawa, review by Richard Eisenberg) + + - [#12968](https://github.com/ocaml/ocaml/issues/12968): Attach location to constants in the parsetree + (Jules Aguillon, review by Gabriel Scherer) + + - [#12959](https://github.com/ocaml/ocaml/issues/12959), [#13055](https://github.com/ocaml/ocaml/issues/13055): Avoid an internal error on recursive module type inconsistency + (Florian Angeletti, review by Jacques Garrigue and Gabriel Scherer) + + - [#13049](https://github.com/ocaml/ocaml/issues/13049): graphical debugging printer for types + (Florian Angeletti, review by Gabriel Scherer) + + - [#13074](https://github.com/ocaml/ocaml/issues/13074), [#13082](https://github.com/ocaml/ocaml/issues/13082), [#13084](https://github.com/ocaml/ocaml/issues/13084): refactoring in the pattern-matching compiler + (Gabriel Scherer, review by Thomas Refis, Vincent Laviron and Nick Roberts) + + - [#13067](https://github.com/ocaml/ocaml/issues/13067): rework volatile memory access rules under TSan to consider properly + aligned smaller-than-register read operations as atomic, which gets rid of + false positives on s390x + (Miod Vallat, review by Fabien Buoro) + + - [#13162](https://github.com/ocaml/ocaml/issues/13162): Use quoted strings to clarify code being generated. + (Antonin Décimo, review by Miod Vallat and Gabriel Scherer) + + - [#13015](https://github.com/ocaml/ocaml/issues/13015): Emit floating-point literals in .rodata section on ELF arm64 + platforms (Linux, *BSD). + (Miod Vallat, review by Nicolás Ojeda Bär) + + - [#13169](https://github.com/ocaml/ocaml/issues/13169), [#13311](https://github.com/ocaml/ocaml/issues/13311): Introduce a document data type for compiler messages + rather than relying on `Format.formatter -> unit` closures. + (Florian Angeletti, review by Gabriel Scherer) + + - [#13193](https://github.com/ocaml/ocaml/issues/13193): Remove the unused env_init field from class blocks + (Vincent Laviron, review by Jacques Garrigue) + + - [#13257](https://github.com/ocaml/ocaml/issues/13257): integrate MetaOCaml in the Menhir grammar to ease MetaOCaml + maintenance. This is a purely internal change: there is no support + in the lexer, so no change to the surface OCaml grammar. + (Oleg Kiselyov, Gabriel Scherer and Florian Angeletti, + review by Jeremy Yallop) + + - [#13289](https://github.com/ocaml/ocaml/issues/13289): Use C99 for loop to reduce the scope of the for loop iterator. + (Antonin Décimo, review by Miod Vallat and Gabriel Scherer) + + - [#13336](https://github.com/ocaml/ocaml/issues/13336): compiler-libs, split the `Printtyp` in three to only keep + "user-friendly" functions in the `Printtyp` module. + (Florian Angeletti, review by Gabriel Scherer) + + - [#13361](https://github.com/ocaml/ocaml/issues/13361): split runtime/array.c functions to consistently expose + uniform_array and floatarray versions, use floatarray versions + in Float.Array. + (Gabriel Scherer, review by Nicolás Ojeda Bär) + + - [#13507](https://github.com/ocaml/ocaml/issues/13507): A small refactoring to [free_vars] to make it a bit faster + by not allocating a list when the list is not necessary. + (Richard Eisenberg, review by Jacques Garrigue) + + ### Build system: + + - [#12909](https://github.com/ocaml/ocaml/issues/12909): Reorganise how MKEXE_VIA_CC is built to make it correct for MSVC by + grouping all the linker flags at the end of the C compiler commandline + (David Allsopp and Samuel Hym, review by Nicolás Ojeda Bär) + + - [#12992](https://github.com/ocaml/ocaml/issues/12992), [#13009](https://github.com/ocaml/ocaml/issues/13009): Check that flexlink can be executed only when building in a + native windows environment. + (Romain Beauxis, review by David Allsopp and Sébastien Hinderer) + + - [#12996](https://github.com/ocaml/ocaml/issues/12996): Only link with -lgcc_eh when available. + (Romain Beauxis, review by David Allsopp and Miod Vallat) + + * (*breaking change*) [#13200](https://github.com/ocaml/ocaml/issues/13200): Do not use CFLAGS for linking. + (Sébastien Hinderer, review by Gabriel Scherer, Antonin Décimo, + Miod Vallat and Samuel Hym) + + - [#13201](https://github.com/ocaml/ocaml/issues/13201), [#13244](https://github.com/ocaml/ocaml/issues/13244): Fix and speedup builds with TSan. + (Sébastien Hinderer, review by Miod Vallat, Gabriel Scherer and + Olivier Nicole) + + * (*breaking change*) [#12578](https://github.com/ocaml/ocaml/issues/12578), [#12589](https://github.com/ocaml/ocaml/issues/12589), [#13322](https://github.com/ocaml/ocaml/issues/13322), [#13519](https://github.com/ocaml/ocaml/issues/13519): Use configured CFLAGS and CPPFLAGS *only* + during the build of the compiler itself. Do not use them when + compiling third-party C sources through the compiler. Flags for + compiling third-party C sources can still be specified at configure + time in the COMPILER_{BYTECODE,NATIVE}_{CFLAGS,CPPFLAGS} + configuration variables. + (Sébastien Hinderer, report by William Hu, review by David Allsopp) + + - [#13285](https://github.com/ocaml/ocaml/issues/13285): continue the merge of the sub-makefiles into the root + Makefile started with [#11243](https://github.com/ocaml/ocaml/issues/11243), [#11248](https://github.com/ocaml/ocaml/issues/11248), [#11268](https://github.com/ocaml/ocaml/issues/11268), [#11420](https://github.com/ocaml/ocaml/issues/11420), [#11675](https://github.com/ocaml/ocaml/issues/11675), + [#12198](https://github.com/ocaml/ocaml/issues/12198), [#12321](https://github.com/ocaml/ocaml/issues/12321), [#12586](https://github.com/ocaml/ocaml/issues/12586), [#12616](https://github.com/ocaml/ocaml/issues/12616), [#12706](https://github.com/ocaml/ocaml/issues/12706) and [#13048](https://github.com/ocaml/ocaml/issues/13048). + (Sébastien Hinderer, review by David Allsopp and Florian Angeletti) + + ### Bug fixes: + + - [#12854](https://github.com/ocaml/ocaml/issues/12854): Add a test in the regression suite that flags the bug [#12825](https://github.com/ocaml/ocaml/issues/12825). + (Luc Maranget) + + - [#12888](https://github.com/ocaml/ocaml/issues/12888): fix printing of uncaught exceptions in `.cmo` files passed on the + command-line of the toplevel. + (Nicolás Ojeda Bär, review by Florian Angeletti, report by Daniel Bünzli) + + - [#12910](https://github.com/ocaml/ocaml/issues/12910), [#12920](https://github.com/ocaml/ocaml/issues/12920): Fix an unsound interaction between first-class modules + and polymorphic records by saving and restoring univar_pairs. + (Stephen Dolan, review by Gabriel Scherer, report by Jeremy Yallop) + + - [#12994](https://github.com/ocaml/ocaml/issues/12994): Remove un-used and unsafe caml_drop_continuation + (Tim McGilchrist, reviewed by Gabriel Scherer and Miod Vallat) + + - [#12963](https://github.com/ocaml/ocaml/issues/12963): Restore caml_runtime_parameters implementation. This primitive allows + programs to query the runtime parameters supplied to an OCaml program. + Implementation missing since OCaml 5.0. + (Tim McGilchrist, reviewed by David Allsopp and Miod Vallat) + + - [#13012](https://github.com/ocaml/ocaml/issues/13012): parsing: Fix dropped attributes after a '-' or '+' + The syntax '-(1 [@foo])' was incorrectly parsed as '-1'. + (Jules Aguillon, reviewed by Gabriel Scherer, report by Gabriel Scherer) + + * (*breaking change*) [#13070](https://github.com/ocaml/ocaml/issues/13070): On Windows, when configured with bootstrapped flexdll, don't add + +flexdll to the search path when -nostdlib is specified (which then means + -L no longer gets passed to the system linker). + (David Allsopp, review by Florian Angeletti) + + - [#13089](https://github.com/ocaml/ocaml/issues/13089): Fix bug in `runtime_events` library which could result in garbled + output under Windows. + (B. Szilvasy, review by Nicolás Ojeda Bär and Miod Vallat) + + - [#13088](https://github.com/ocaml/ocaml/issues/13088): A few type-checker behaviors look at a type to see if there are + any labeled arguments in it. This sometimes required expansion, which + could, in obscure scenarios, result in superfluous type errors. + (Richard Eisenberg, review by Gabriel Scherer and Jacques Garrigue) + + - [#13103](https://github.com/ocaml/ocaml/issues/13103): FreeBSD/amd64: properly annotate .o files with non-executable stack + notes (Konstantin Belousov, review by Nicolás Ojeda Bär) + + - [#13150](https://github.com/ocaml/ocaml/issues/13150): improve a transitive-closure computation algorithm in the flambda + middle-end to avoid a compilation time blowup on Menhir-generated code + (Florian Weimer, review by Gabriel Scherer and Pierre Chambart, + report by Richard Jones) + + - [#13166](https://github.com/ocaml/ocaml/issues/13166): Fix a MinGW/MSVC Sys.rename regression on renaming a parent directory + to an empty child directory. + (Jan Midtgaard, review by Antonin Décimo, Sébastien Hinderer, and + David Allsopp) + + - [#13185](https://github.com/ocaml/ocaml/issues/13185), [#13192](https://github.com/ocaml/ocaml/issues/13192): Reject type-level module aliases on functor parameter + inside signatures. + (Jacques Garrigue, report by Richard Eisenberg, review by Florian Angeletti) + + - [#13170](https://github.com/ocaml/ocaml/issues/13170): Fix a bug that would result in some floating alerts `[@@@alert ...]` + incorrectly triggering Warning 53. + (Nicolás Ojeda Bär, review by Chris Casinghino and Florian Angeletti) + + - [#13203](https://github.com/ocaml/ocaml/issues/13203): Do not issue warning 53 if the compiler is stopping before attributes + have been accurately marked. + (Chris Casinghino, review by Florian Angeletti) + + - [#13207](https://github.com/ocaml/ocaml/issues/13207): Be sure to reload the register caching the exception handler in + caml_c_call and caml_c_call_stack_args, as its value may have been changed + if the OCaml stack is expanded during a callback. + (Miod Vallat, report by Vesa Karvonen, review by Gabriel Scherer and + Xavier Leroy) + + - [#13209](https://github.com/ocaml/ocaml/issues/13209): Fix configure test that checks whether `ar` supports `@FILE` + arguments. + (Nicolás Ojeda Bär, report by Boris D.) + + - [#13221](https://github.com/ocaml/ocaml/issues/13221): Compute more accurate instruction sizes for branch relocation on + POWER. + (Miod Vallat, review by Gabriel Scherer) + + - [#13252](https://github.com/ocaml/ocaml/issues/13252): Rework register assignment in the interpreter code on m68k on Linux, + due to the %a5 register being used by Glibc. + (Miod Vallat, report by Stéphane Glondu, review by Gabriel Scherer and + Xavier Leroy) + + - [#13247](https://github.com/ocaml/ocaml/issues/13247): Disable lib_unix/kill test for MacOS AMD64 with TSan, linking + to llvm bug report causing infinite signal loops. + (Tim McGilchrist, review by Olivier Nicole, Miod Vallat, Sébastien Hinderer + and Gabriel Scherer) + + - [#13234](https://github.com/ocaml/ocaml/issues/13234), [#13267](https://github.com/ocaml/ocaml/issues/13267): Open runtime events file in read-write mode on armel + (armv5) systems due to atomic operations limitations on that + platform. + (Stéphane Glondu, review by Miod Vallat and Vincent Laviron) + + - [#13273](https://github.com/ocaml/ocaml/issues/13273): Fix a call to test in configure.ac that was causing errors when + LDFLAGS contains several words. + (Stéphane Glondu, review by Miod Vallat) + + - [#13290](https://github.com/ocaml/ocaml/issues/13290): Fix uninitialized and out of bounds reads in runtime_events_consumer.c + (Edwin Török, review by Miod Vallat and Antonin Décimo) + + - [#13306](https://github.com/ocaml/ocaml/issues/13306): An algorithm in the type-checker that checks two types for equality + could sometimes, in theory, return the wrong answer. This patch fixes the + oversight. No known program triggers the bug. + (Richard Eisenberg, review by Florian Angeletti) + + - [#13400](https://github.com/ocaml/ocaml/issues/13400): Initialize th->signal_stack to avoid free of uninitialized data + if the user calls caml_c_thread_unregister on the main thread. + (Richard W.M. Jones, review by Guillaume Munch-Maccagnoni and + Gabriel Scherer) + + - [#13140](https://github.com/ocaml/ocaml/issues/13140): POWER back-end: fix issue with call to `caml_call_realloc_stack` + from a DLL + (Xavier Leroy, review by Miod Vallat) + + - [#13263](https://github.com/ocaml/ocaml/issues/13263), [#13560](https://github.com/ocaml/ocaml/issues/13560): fix printing true and false in toplevel and error + messages (no more unexpected \#true) + (Florian Angeletti, report by Samuel Vivien, review by Gabriel Scherer) + + - [#13388](https://github.com/ocaml/ocaml/issues/13388), [#13540](https://github.com/ocaml/ocaml/issues/13540): raises an error message (and not an internal compiler error) + when two local substitutions are incompatible (for instance `module type + S:=sig end type t:=(module S)`) + (Florian Angeletti, report by Nailen Matschke, review by Gabriel Scherer, and + Leo White) + + - [#13408](https://github.com/ocaml/ocaml/issues/13408): Fix misplaced debug runtime assertion triggerable by a race + between domain exit and backup thread + (Miod Vallat and Gabriel Scherer, report by Jan Midtgaard) + + - [#13417](https://github.com/ocaml/ocaml/issues/13417): `Filename.quote_command`: fix handling of forward slashes in program + path under Win32. + (Nicolás Ojeda Bär, review by David Allsopp and Damien Doligez) + + - [#13501](https://github.com/ocaml/ocaml/issues/13501): Regression on mutually recursive types caused by [#12180](https://github.com/ocaml/ocaml/issues/12180). + Resuscitate Typedecl.update_type. + (Jacques Garrigue and Takafumi Saikawa, review by Florian Angeletti, Richard + Eisenberg and Gabriel Scherer) + + - [#13502](https://github.com/ocaml/ocaml/issues/13502): Fix misindexing related to `Gc.finalise_last` that could prevent + finalisers from being run. + (Nick Roberts, review by Mark Shinwell) + + - [#13495](https://github.com/ocaml/ocaml/issues/13495), [#13514](https://github.com/ocaml/ocaml/issues/13514): Fix typechecker crash while typing objects + (Jacques Garrigue, report by Nicolás Ojeda Bär, review by + Nicolas Ojeda Bär, Gabriel Scherer, Stephen Dolan, Florian Angeletti) + + - [#13391](https://github.com/ocaml/ocaml/issues/13391), [#13551](https://github.com/ocaml/ocaml/issues/13551): fix a printing bug with `-dsource` when using + raw literal inside a locally abstract type constraint + (i.e. `let f: type \#for. ... `) + (Florian Angeletti, report by Nick Roberts, review by Richard Eisenberg) + + - [#13520](https://github.com/ocaml/ocaml/issues/13520): Fix compilation of native-code version of systhreads. Bytecode fields + were being included in the thread descriptors. + (David Allsopp, review by Sébastien Hinderer and Miod Vallat) + + - [#13541](https://github.com/ocaml/ocaml/issues/13541), [#13591](https://github.com/ocaml/ocaml/issues/13591): Fix headers for C++ inclusion. + (Antonin Décimo, review by Nick Barnes, report by Kate Deplaix) + + - [#13579](https://github.com/ocaml/ocaml/issues/13579), [#13583](https://github.com/ocaml/ocaml/issues/13583): Unsoundness involving non-injective types + gadts + (Jacques Garrigue, report by @v-gb, + review by Richard Eisenberg and Florian Angeletti) + + - [#13598](https://github.com/ocaml/ocaml/issues/13598): Falsely triggered warning 56 [unreachable-case] + This was caused by unproper protection of the retyping function. + (Jacques Garrigue, report by Tõivo Leedjärv, review by Florian Angeletti) + + - [#13603](https://github.com/ocaml/ocaml/issues/13603), [#13604](https://github.com/ocaml/ocaml/issues/13604): fix source printing in the presence of the escaped raw + identifier `\#mod`. + (Florian Angeletti, report by Chris Casinghino, review by Gabriel Scherer) +--- + +We have the pleasure of announcing the release of OCaml version 5.3.0. dedicated +to the memory of John William Mauchly and Paul Verlaine on the anniversary of +their death. + +> De la musique avant toute chose, +> Et pour cela préfère l’Impair + +> (Music first and foremost of all! +> Choose your measure of odd not even) + +Some of the highlights in OCaml 5.3.0 are: + +- Syntax for deep effect handlers + + There is now a dedicated syntax for installing deep effect handler + ```ocaml + match f () with + | x -> x + | effect Random_float, k -> Effect.Deep.continue k (Random.float 1.0) + ``` + This new syntax adds a new `effect` keyword, which may break existing code. + To improve backward compatibility, this new keyword can be disabled with + the new `-keywords` flags if needed for backward compatibility. + +- Restored MSVC port + + It is now possible to use the MSVC toolchain on Windows, restoring the last + missing port from OCaml 4 (except for the native compiler support for 32-bit + architectures which is not planned) + +- Re-introduced statistical memory profiling (statmemprof) + + The submodule `Gc.memprof` is restored with a slightly different API. This + submodule can be used to monitor memory allocation statistics inside a + program. In OCaml 5, each domain can be monitored independently while child + domains inherit the parent domain profiling profile (if there is one active). + +- utf-8 encoded Unicode source files and modest support of Unicode identifiers + ```ocaml + type saison = Hiver | Été | Printemps | Automne + ``` + The OCaml lexer has been extended to support a modest subset of Unicode + characters in identifiers. This is mostly intended for pedagogical use. This + extended support requires source files to be utf-8 encoded Unicode text. + +- More space-efficient implementation of Dynarray + + The internal implementation of `Dynarray` now uses an unboxed representation + which avoids the need of storing items wrapped in a `Some x` block and thus + saves some spaces and indirections. + +- Improved metadata on the pairs of declarations and definitions for merlin. + + The metadata stored inside cmt files has been improved to better distinguish the provenance of identifiers (previous versions could confuse an interface and implementation identifier). + Similarly, the metadata now tracks more precisely the association between declarations and definitions. For instance, in + ```ocaml + module X = struct let x = 0 end + module M: sig + val x: int + end = struct + let x = 1 + include X + end + ``` + Merlin can now determine that the definition of the `M.x` value lies inside the module `X`. + +And a lot of incremental changes: + +- Around 20 new functions in the standard library (in the `Domain`, `Dynarray` +`Format`, `List`, `Queue`, `Sys`, and `Uchar` modules). +- Many fixes and improvements in the runtime +- Improved error messages for first-class modules, functors, labelled arguments, + and type clashes. +- Numerous bug fixes + +Please report any unexpected behaviours on the [OCaml issue tracker](https://github.com/ocaml/ocaml/issues) +and post any questions or comments you might have on our +[discussion forums](https://discuss.ocaml.org). + + +The full list of changes can be found in the full changelog. + +--- + +## Installation Instructions + +The base compiler can be installed as an opam switch with the following commands: +```bash +opam update +opam switch create 5.3.0 +``` + +The source code for the release is also directly available on: + +* [GitHub](https://github.com/ocaml/ocaml/releases/download/5.3.0/ocaml-5.3.0.tar.gz) +* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.3/ocaml-5.3.0.tar.gz) + +### Fine-Tuned Compiler Configuration + +If you want to tweak the configuration of the compiler, you can switch to the option variant with: +```bash +opam update +opam switch create ocaml-variants.5.3.0+options +``` +where `` is a space separated list of `ocaml-option-*` packages. For instance, for a `flambda` and `no-flat-float-array` switch: +```bash +opam switch create 5.3.0+flambda+nffa ocaml-variants.5.3.0+options ocaml-option-flambda ocaml-option-no-flat-float-array +``` diff --git a/data/changelog/ocamlformat/2017-12-22-ocamlformat-0.3.md b/data/changelog/releases/ocamlformat/2017-12-22-ocamlformat-0.3.md similarity index 100% rename from data/changelog/ocamlformat/2017-12-22-ocamlformat-0.3.md rename to data/changelog/releases/ocamlformat/2017-12-22-ocamlformat-0.3.md diff --git a/data/changelog/ocamlformat/2018-01-08-ocamlformat-0.2.md b/data/changelog/releases/ocamlformat/2018-01-08-ocamlformat-0.2.md similarity index 100% rename from data/changelog/ocamlformat/2018-01-08-ocamlformat-0.2.md rename to data/changelog/releases/ocamlformat/2018-01-08-ocamlformat-0.2.md diff --git a/data/changelog/ocamlformat/2018-02-24-ocamlformat-0.4.md b/data/changelog/releases/ocamlformat/2018-02-24-ocamlformat-0.4.md similarity index 100% rename from data/changelog/ocamlformat/2018-02-24-ocamlformat-0.4.md rename to data/changelog/releases/ocamlformat/2018-02-24-ocamlformat-0.4.md diff --git a/data/changelog/ocamlformat/2018-04-17-ocamlformat-0.5.md b/data/changelog/releases/ocamlformat/2018-04-17-ocamlformat-0.5.md similarity index 100% rename from data/changelog/ocamlformat/2018-04-17-ocamlformat-0.5.md rename to data/changelog/releases/ocamlformat/2018-04-17-ocamlformat-0.5.md diff --git a/data/changelog/ocamlformat/2018-04-30-ocamlformat-0.6.md b/data/changelog/releases/ocamlformat/2018-04-30-ocamlformat-0.6.md similarity index 100% rename from data/changelog/ocamlformat/2018-04-30-ocamlformat-0.6.md rename to data/changelog/releases/ocamlformat/2018-04-30-ocamlformat-0.6.md diff --git a/data/changelog/ocamlformat/2018-08-24-ocamlformat-0.7.md b/data/changelog/releases/ocamlformat/2018-08-24-ocamlformat-0.7.md similarity index 100% rename from data/changelog/ocamlformat/2018-08-24-ocamlformat-0.7.md rename to data/changelog/releases/ocamlformat/2018-08-24-ocamlformat-0.7.md diff --git a/data/changelog/ocamlformat/2018-10-10-ocamlformat-0.8.md b/data/changelog/releases/ocamlformat/2018-10-10-ocamlformat-0.8.md similarity index 100% rename from data/changelog/ocamlformat/2018-10-10-ocamlformat-0.8.md rename to data/changelog/releases/ocamlformat/2018-10-10-ocamlformat-0.8.md diff --git a/data/changelog/ocamlformat/2019-03-28-ocamlformat-0.9.md b/data/changelog/releases/ocamlformat/2019-03-28-ocamlformat-0.9.md similarity index 100% rename from data/changelog/ocamlformat/2019-03-28-ocamlformat-0.9.md rename to data/changelog/releases/ocamlformat/2019-03-28-ocamlformat-0.9.md diff --git a/data/changelog/ocamlformat/2019-06-24-ocamlformat-0.9.1.md b/data/changelog/releases/ocamlformat/2019-06-24-ocamlformat-0.9.1.md similarity index 100% rename from data/changelog/ocamlformat/2019-06-24-ocamlformat-0.9.1.md rename to data/changelog/releases/ocamlformat/2019-06-24-ocamlformat-0.9.1.md diff --git a/data/changelog/ocamlformat/2019-06-27-ocamlformat-0.10.md b/data/changelog/releases/ocamlformat/2019-06-27-ocamlformat-0.10.md similarity index 100% rename from data/changelog/ocamlformat/2019-06-27-ocamlformat-0.10.md rename to data/changelog/releases/ocamlformat/2019-06-27-ocamlformat-0.10.md diff --git a/data/changelog/ocamlformat/2019-08-07-ocamlformat-0.11.0.md b/data/changelog/releases/ocamlformat/2019-08-07-ocamlformat-0.11.0.md similarity index 100% rename from data/changelog/ocamlformat/2019-08-07-ocamlformat-0.11.0.md rename to data/changelog/releases/ocamlformat/2019-08-07-ocamlformat-0.11.0.md diff --git a/data/changelog/ocamlformat/2019-11-04-ocamlformat-0.12.md b/data/changelog/releases/ocamlformat/2019-11-04-ocamlformat-0.12.md similarity index 100% rename from data/changelog/ocamlformat/2019-11-04-ocamlformat-0.12.md rename to data/changelog/releases/ocamlformat/2019-11-04-ocamlformat-0.12.md diff --git a/data/changelog/ocamlformat/2020-01-30-ocamlformat-0.13.0.md b/data/changelog/releases/ocamlformat/2020-01-30-ocamlformat-0.13.0.md similarity index 100% rename from data/changelog/ocamlformat/2020-01-30-ocamlformat-0.13.0.md rename to data/changelog/releases/ocamlformat/2020-01-30-ocamlformat-0.13.0.md diff --git a/data/changelog/ocamlformat/2020-04-02-ocamlformat-0.14.0.md b/data/changelog/releases/ocamlformat/2020-04-02-ocamlformat-0.14.0.md similarity index 100% rename from data/changelog/ocamlformat/2020-04-02-ocamlformat-0.14.0.md rename to data/changelog/releases/ocamlformat/2020-04-02-ocamlformat-0.14.0.md diff --git a/data/changelog/ocamlformat/2020-04-14-ocamlformat-0.14.1.md b/data/changelog/releases/ocamlformat/2020-04-14-ocamlformat-0.14.1.md similarity index 100% rename from data/changelog/ocamlformat/2020-04-14-ocamlformat-0.14.1.md rename to data/changelog/releases/ocamlformat/2020-04-14-ocamlformat-0.14.1.md diff --git a/data/changelog/ocamlformat/2020-05-11-ocamlformat-0.14.2.md b/data/changelog/releases/ocamlformat/2020-05-11-ocamlformat-0.14.2.md similarity index 100% rename from data/changelog/ocamlformat/2020-05-11-ocamlformat-0.14.2.md rename to data/changelog/releases/ocamlformat/2020-05-11-ocamlformat-0.14.2.md diff --git a/data/changelog/ocamlformat/2020-07-23-ocamlformat-0.14.3.md b/data/changelog/releases/ocamlformat/2020-07-23-ocamlformat-0.14.3.md similarity index 100% rename from data/changelog/ocamlformat/2020-07-23-ocamlformat-0.14.3.md rename to data/changelog/releases/ocamlformat/2020-07-23-ocamlformat-0.14.3.md diff --git a/data/changelog/ocamlformat/2020-08-06-ocamlformat-0.15.0.md b/data/changelog/releases/ocamlformat/2020-08-06-ocamlformat-0.15.0.md similarity index 100% rename from data/changelog/ocamlformat/2020-08-06-ocamlformat-0.15.0.md rename to data/changelog/releases/ocamlformat/2020-08-06-ocamlformat-0.15.0.md diff --git a/data/changelog/ocamlformat/2020-11-03-ocamlformat-0.15.1.md b/data/changelog/releases/ocamlformat/2020-11-03-ocamlformat-0.15.1.md similarity index 100% rename from data/changelog/ocamlformat/2020-11-03-ocamlformat-0.15.1.md rename to data/changelog/releases/ocamlformat/2020-11-03-ocamlformat-0.15.1.md diff --git a/data/changelog/ocamlformat/2020-11-17-ocamlformat-0.16.0.md b/data/changelog/releases/ocamlformat/2020-11-17-ocamlformat-0.16.0.md similarity index 100% rename from data/changelog/ocamlformat/2020-11-17-ocamlformat-0.16.0.md rename to data/changelog/releases/ocamlformat/2020-11-17-ocamlformat-0.16.0.md diff --git a/data/changelog/ocamlformat/2021-02-16-ocamlformat-0.17.0.md b/data/changelog/releases/ocamlformat/2021-02-16-ocamlformat-0.17.0.md similarity index 100% rename from data/changelog/ocamlformat/2021-02-16-ocamlformat-0.17.0.md rename to data/changelog/releases/ocamlformat/2021-02-16-ocamlformat-0.17.0.md diff --git a/data/changelog/ocamlformat/2021-04-01-ocamlformat-0.18.0.md b/data/changelog/releases/ocamlformat/2021-04-01-ocamlformat-0.18.0.md similarity index 100% rename from data/changelog/ocamlformat/2021-04-01-ocamlformat-0.18.0.md rename to data/changelog/releases/ocamlformat/2021-04-01-ocamlformat-0.18.0.md diff --git a/data/changelog/ocamlformat/2021-07-19-ocamlformat-0.19.0.md b/data/changelog/releases/ocamlformat/2021-07-19-ocamlformat-0.19.0.md similarity index 100% rename from data/changelog/ocamlformat/2021-07-19-ocamlformat-0.19.0.md rename to data/changelog/releases/ocamlformat/2021-07-19-ocamlformat-0.19.0.md diff --git a/data/changelog/ocamlformat/2021-12-06-ocamlformat-0.20.0.md b/data/changelog/releases/ocamlformat/2021-12-06-ocamlformat-0.20.0.md similarity index 100% rename from data/changelog/ocamlformat/2021-12-06-ocamlformat-0.20.0.md rename to data/changelog/releases/ocamlformat/2021-12-06-ocamlformat-0.20.0.md diff --git a/data/changelog/ocamlformat/2021-12-13-ocamlformat-0.20.1.md b/data/changelog/releases/ocamlformat/2021-12-13-ocamlformat-0.20.1.md similarity index 100% rename from data/changelog/ocamlformat/2021-12-13-ocamlformat-0.20.1.md rename to data/changelog/releases/ocamlformat/2021-12-13-ocamlformat-0.20.1.md diff --git a/data/changelog/ocamlformat/2022-02-28-ocamlformat-0.21.0.md b/data/changelog/releases/ocamlformat/2022-02-28-ocamlformat-0.21.0.md similarity index 100% rename from data/changelog/ocamlformat/2022-02-28-ocamlformat-0.21.0.md rename to data/changelog/releases/ocamlformat/2022-02-28-ocamlformat-0.21.0.md diff --git a/data/changelog/ocamlformat/2022-05-26-ocamlformat-0.22.4.md b/data/changelog/releases/ocamlformat/2022-05-26-ocamlformat-0.22.4.md similarity index 100% rename from data/changelog/ocamlformat/2022-05-26-ocamlformat-0.22.4.md rename to data/changelog/releases/ocamlformat/2022-05-26-ocamlformat-0.22.4.md diff --git a/data/changelog/ocamlformat/2022-07-07-ocamlformat-0.23.0.md b/data/changelog/releases/ocamlformat/2022-07-07-ocamlformat-0.23.0.md similarity index 100% rename from data/changelog/ocamlformat/2022-07-07-ocamlformat-0.23.0.md rename to data/changelog/releases/ocamlformat/2022-07-07-ocamlformat-0.23.0.md diff --git a/data/changelog/ocamlformat/2022-07-18-ocamlformat-0.24.1.md b/data/changelog/releases/ocamlformat/2022-07-18-ocamlformat-0.24.1.md similarity index 100% rename from data/changelog/ocamlformat/2022-07-18-ocamlformat-0.24.1.md rename to data/changelog/releases/ocamlformat/2022-07-18-ocamlformat-0.24.1.md diff --git a/data/changelog/ocamlformat/2023-03-06-ocamlformat-0.25.1.md b/data/changelog/releases/ocamlformat/2023-03-06-ocamlformat-0.25.1.md similarity index 100% rename from data/changelog/ocamlformat/2023-03-06-ocamlformat-0.25.1.md rename to data/changelog/releases/ocamlformat/2023-03-06-ocamlformat-0.25.1.md diff --git a/data/changelog/ocamlformat/2023-07-20-ocamlformat-0.26.0.md b/data/changelog/releases/ocamlformat/2023-07-20-ocamlformat-0.26.0.md similarity index 100% rename from data/changelog/ocamlformat/2023-07-20-ocamlformat-0.26.0.md rename to data/changelog/releases/ocamlformat/2023-07-20-ocamlformat-0.26.0.md diff --git a/data/changelog/ocamlformat/2023-09-19-ocamlformat-0.26.1.md b/data/changelog/releases/ocamlformat/2023-09-19-ocamlformat-0.26.1.md similarity index 100% rename from data/changelog/ocamlformat/2023-09-19-ocamlformat-0.26.1.md rename to data/changelog/releases/ocamlformat/2023-09-19-ocamlformat-0.26.1.md diff --git a/data/changelog/ocamlformat/2024-04-23-ocamlformat-0.26.2.md b/data/changelog/releases/ocamlformat/2024-04-23-ocamlformat-0.26.2.md similarity index 100% rename from data/changelog/ocamlformat/2024-04-23-ocamlformat-0.26.2.md rename to data/changelog/releases/ocamlformat/2024-04-23-ocamlformat-0.26.2.md diff --git a/data/changelog/releases/ocamlformat/2024-12-02-ocamlformat-0.27.0.md b/data/changelog/releases/ocamlformat/2024-12-02-ocamlformat-0.27.0.md new file mode 100644 index 0000000000..fcc3b0fd1a --- /dev/null +++ b/data/changelog/releases/ocamlformat/2024-12-02-ocamlformat-0.27.0.md @@ -0,0 +1,130 @@ +--- +title: OCamlformat 0.27.0 +tags: [ocamlformat, platform] +changelog: | + ### Highlight + + - \* Support OCaml 5.2 syntax (#2519, #2544, #2590, #2596, #2621, #2628, @Julow, @EmileTrotignon, @hhugo) + This includes local open in types, raw identifiers, and the new + representation for functions. + This might change the formatting of some functions due to the formatting code + being completely rewritten. + + - Support OCaml 5.3 syntax (#2609, #2610, #2611, #2622, #2623, #2562, #2624, #2625, #2627, @Julow, @Zeta611) + This adds support for effect patterns, short functor type arguments and utf8 + identifiers. + To format code using the new `effect` syntax, add this option to your + `.ocamlformat`: + ``` + ocaml-version = 5.3 + ``` + + - Documentation comments are now formatted by default (#2390, @Julow) + Use the option `parse-docstrings = false` to restore the previous behavior. + + - \* Consistent indentation of polymorphic variant arguments (#2427, @Julow) + Increases the indentation by one to make the formatting consistent with + normal variants. For example: + ``` + ... + (* before *) + (`Msg + (foo bar)) + (* after *) + (`Msg + (foo bar)) + ``` + + - Build on OCaml 5.3 (#2603, @adamchol, @Julow) + + ### Added + + - Improve the emacs plugin (#2577, #2600, @gridbugs, @thibautbenjamin) + Allow a custom command to be used to run ocamlformat and add compatibility + with emacs ocaml tree-sitter modes. + + - Added option `let-binding-deindent-fun` (#2521, @henrytill) + to control the indentation of the `fun` in: + ``` + let f = + fun foo -> + bar + ``` + + - Added back the flag `--disable-outside-detected-project` (#2439, @gpetiot) + It was removed in version 0.22. + + - Support newer Odoc syntax (#2631, #2632, #2633, @Julow) + + ### Changed + + - \* Consistent formatting of comments (#2371, #2550, @Julow) + This is mostly an internal change but some comments might be formatted differently. + + - \* Improve formatting of type constraints with type variables (#2437, @gpetiot) + For example: + ``` + let f : type a b c. + a -> b -> c = + ... + ``` + + - \* Improve formatting of functor arguments (#2505, @Julow) + This also reduce the indentation of functor arguments with long signatures. + + - Improvements to the Janestreet profile (#2445, #2314, #2460, #2593, #2612, @Julow, @tdelvecchio-jsc) + + - \* Undo let-bindings and methods normalizations (#2523, #2529, @gpetiot) + This remove the rewriting of some forms of let-bindings and methods: + + `let f x = (x : int)` is no longer rewritten into `let f x : int = x` + + `let f (type a) (type b) ...` is no longer rewritten into `let f (type a b) ...` + + `let f = fun x -> ...` is no longer rewritten into `let f x = ...` + + - \* The `break-colon` option is now taken into account for method type constraints (#2529, @gpetiot) + + - \* Force a break around comments following an infix operator (fix non-stabilizing comments) (#2478, @gpetiot) + This adds a line break: + ``` + a + || + (* this comment is now on its own line *) + b + ``` + + ### Fixed + + - Fix placement of comments in some cases (#2471, #2503, #2506, #2540, #2541, #2592, #2617, @gpetiot, @Julow) + Some comments were being moved or causing OCamlformat to crash. + OCamlformat refuses to format if a comment would be missing in its output, to avoid loosing code. + + - Fix attributes being dropped or moved (#2247, #2459, #2551, #2564, #2602, @EmileTrotignon, @tdelvecchio-jsc, @Julow) + OCamlformat refuses to format if the formatted code has a different meaning than the original code, for example, if an attribute is removed. + We also try to avoid moving attributes even if that doesn't change the original code, for example we no longer format `open[@attr] M` as `open M [@@attr]`. + + - Remove trailing space inside a wrapping empty signature (#2443, @Julow) + - Fix extension-point spacing in structures (#2450, @Julow) + - \* Consistent break after string constant argument (#2453, @Julow) + - \* Fix cinaps comment formatting to not change multiline string contents (#2463, @tdelvecchio-jsc) + - \* Fix the indentation of tuples in attributes and extensions (#2488, @Julow) + - \* Fix weird indentation and line breaks after comments (#2507, #2589, #2606, @Julow) + - \* Fix unwanted alignment in if-then-else (#2511, @Julow) + - Fix missing parentheses around constraint expressions with attributes (#2513, @alanechang) + - Fix formatting of type vars in GADT constructors (#2518, @Julow) + - Fix `[@ocamlformat "disable"]` in some cases (#2242, #2525, @EmileTrotignon) + This caused a bug inside `class type` constructs and when attached to a `let ... in` + - Display `a##b` instead of `a ## b` and similarly for operators that start with # (#2580, @v-gb) + - \* Fix arrow type indentation with `break-separators=before` (#2598, @Julow) + - Fix missing parentheses around a let in class expressions (#2599, @Julow) + - Fix formatting of paragraphs in lists in documentation (#2607, @Julow) + - Avoid unwanted space in references and links text in documentation (#2608, @Julow) + - \* Improve the indentation of attributes in patterns (#2613, @Julow) + - \* Avoid large indentation in patterns after `let%ext` (#2615, @Julow) +--- + +After almost a year of work, OCamlformat 0.27.0 is finally available with +support for 5.3 syntax! + +This release includes the new function syntax from OCaml 5.2, the `effect` +keyword from OCaml 5.3 and a large number of bug fixes and improvements. + +An other notable change, is that comments are now formatted by default. diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-0.1.0.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.1.0.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-0.1.0.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.1.0.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-0.6.0.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.6.0.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-0.6.0.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.6.0.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-0.6.1.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.6.1.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-0.6.1.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.6.1.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-0.6.2.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.6.2.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-0.6.2.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.6.2.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-0.9.0.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.9.0.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-0.9.0.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.9.0.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-0.9.2.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.9.2.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-0.9.2.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-0.9.2.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-1.0.0.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.0.0.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-1.0.0.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.0.0.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-1.0.1.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.0.1.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-1.0.1.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.0.1.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-1.0.2.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.0.2.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-1.0.2.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.0.2.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-1.1.0.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.1.0.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-1.1.0.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.1.0.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-1.2.0.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.2.0.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-1.2.0.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.2.0.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-1.2.1.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.2.1.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-1.2.1.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.2.1.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-1.2.2.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.2.2.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-1.2.2.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.2.2.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-1.3.0.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.3.0.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-1.3.0.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.3.0.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-1.3.1.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.3.1.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-1.3.1.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.3.1.md diff --git a/data/changelog/ocp-indent/2013-11-21-ocp-indent-1.3.2.md b/data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.3.2.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-21-ocp-indent-1.3.2.md rename to data/changelog/releases/ocp-indent/2013-11-21-ocp-indent-1.3.2.md diff --git a/data/changelog/ocp-indent/2013-11-22-ocp-indent-1.4.0.md b/data/changelog/releases/ocp-indent/2013-11-22-ocp-indent-1.4.0.md similarity index 100% rename from data/changelog/ocp-indent/2013-11-22-ocp-indent-1.4.0.md rename to data/changelog/releases/ocp-indent/2013-11-22-ocp-indent-1.4.0.md diff --git a/data/changelog/ocp-indent/2014-01-15-ocp-indent-1.4.1.md b/data/changelog/releases/ocp-indent/2014-01-15-ocp-indent-1.4.1.md similarity index 100% rename from data/changelog/ocp-indent/2014-01-15-ocp-indent-1.4.1.md rename to data/changelog/releases/ocp-indent/2014-01-15-ocp-indent-1.4.1.md diff --git a/data/changelog/ocp-indent/2014-08-27-ocp-indent-1.4.2.md b/data/changelog/releases/ocp-indent/2014-08-27-ocp-indent-1.4.2.md similarity index 100% rename from data/changelog/ocp-indent/2014-08-27-ocp-indent-1.4.2.md rename to data/changelog/releases/ocp-indent/2014-08-27-ocp-indent-1.4.2.md diff --git a/data/changelog/ocp-indent/2015-02-28-ocp-indent-1.5.md b/data/changelog/releases/ocp-indent/2015-02-28-ocp-indent-1.5.md similarity index 100% rename from data/changelog/ocp-indent/2015-02-28-ocp-indent-1.5.md rename to data/changelog/releases/ocp-indent/2015-02-28-ocp-indent-1.5.md diff --git a/data/changelog/ocp-indent/2015-09-04-ocp-indent-1.5.1.md b/data/changelog/releases/ocp-indent/2015-09-04-ocp-indent-1.5.1.md similarity index 100% rename from data/changelog/ocp-indent/2015-09-04-ocp-indent-1.5.1.md rename to data/changelog/releases/ocp-indent/2015-09-04-ocp-indent-1.5.1.md diff --git a/data/changelog/ocp-indent/2015-10-13-ocp-indent-1.5.2.md b/data/changelog/releases/ocp-indent/2015-10-13-ocp-indent-1.5.2.md similarity index 100% rename from data/changelog/ocp-indent/2015-10-13-ocp-indent-1.5.2.md rename to data/changelog/releases/ocp-indent/2015-10-13-ocp-indent-1.5.2.md diff --git a/data/changelog/ocp-indent/2016-06-24-ocp-indent-1.5.3.md b/data/changelog/releases/ocp-indent/2016-06-24-ocp-indent-1.5.3.md similarity index 100% rename from data/changelog/ocp-indent/2016-06-24-ocp-indent-1.5.3.md rename to data/changelog/releases/ocp-indent/2016-06-24-ocp-indent-1.5.3.md diff --git a/data/changelog/ocp-indent/2017-03-08-ocp-indent-1.6.0.md b/data/changelog/releases/ocp-indent/2017-03-08-ocp-indent-1.6.0.md similarity index 100% rename from data/changelog/ocp-indent/2017-03-08-ocp-indent-1.6.0.md rename to data/changelog/releases/ocp-indent/2017-03-08-ocp-indent-1.6.0.md diff --git a/data/changelog/ocp-indent/2017-08-04-ocp-indent-1.6.1.md b/data/changelog/releases/ocp-indent/2017-08-04-ocp-indent-1.6.1.md similarity index 100% rename from data/changelog/ocp-indent/2017-08-04-ocp-indent-1.6.1.md rename to data/changelog/releases/ocp-indent/2017-08-04-ocp-indent-1.6.1.md diff --git a/data/changelog/ocp-indent/2018-11-19-ocp-indent-1.7.0.md b/data/changelog/releases/ocp-indent/2018-11-19-ocp-indent-1.7.0.md similarity index 100% rename from data/changelog/ocp-indent/2018-11-19-ocp-indent-1.7.0.md rename to data/changelog/releases/ocp-indent/2018-11-19-ocp-indent-1.7.0.md diff --git a/data/changelog/ocp-indent/2019-09-18-ocp-indent-1.8.0.md b/data/changelog/releases/ocp-indent/2019-09-18-ocp-indent-1.8.0.md similarity index 100% rename from data/changelog/ocp-indent/2019-09-18-ocp-indent-1.8.0.md rename to data/changelog/releases/ocp-indent/2019-09-18-ocp-indent-1.8.0.md diff --git a/data/changelog/ocp-indent/2019-10-24-ocp-indent-1.8.1.md b/data/changelog/releases/ocp-indent/2019-10-24-ocp-indent-1.8.1.md similarity index 100% rename from data/changelog/ocp-indent/2019-10-24-ocp-indent-1.8.1.md rename to data/changelog/releases/ocp-indent/2019-10-24-ocp-indent-1.8.1.md diff --git a/data/changelog/odoc/2017-03-15-odoc-1.0.0.md b/data/changelog/releases/odoc/2017-03-15-odoc-1.0.0.md similarity index 100% rename from data/changelog/odoc/2017-03-15-odoc-1.0.0.md rename to data/changelog/releases/odoc/2017-03-15-odoc-1.0.0.md diff --git a/data/changelog/odoc/2017-05-23-odoc-1.1.0.md b/data/changelog/releases/odoc/2017-05-23-odoc-1.1.0.md similarity index 100% rename from data/changelog/odoc/2017-05-23-odoc-1.1.0.md rename to data/changelog/releases/odoc/2017-05-23-odoc-1.1.0.md diff --git a/data/changelog/odoc/2017-05-31-odoc-1.1.1.md b/data/changelog/releases/odoc/2017-05-31-odoc-1.1.1.md similarity index 100% rename from data/changelog/odoc/2017-05-31-odoc-1.1.1.md rename to data/changelog/releases/odoc/2017-05-31-odoc-1.1.1.md diff --git a/data/changelog/odoc/2017-11-24-odoc-1.2.0.md b/data/changelog/releases/odoc/2017-11-24-odoc-1.2.0.md similarity index 100% rename from data/changelog/odoc/2017-11-24-odoc-1.2.0.md rename to data/changelog/releases/odoc/2017-11-24-odoc-1.2.0.md diff --git a/data/changelog/odoc/2018-10-16-odoc-1.3.0.md b/data/changelog/releases/odoc/2018-10-16-odoc-1.3.0.md similarity index 100% rename from data/changelog/odoc/2018-10-16-odoc-1.3.0.md rename to data/changelog/releases/odoc/2018-10-16-odoc-1.3.0.md diff --git a/data/changelog/odoc/2019-03-08-odoc-1.4.0.md b/data/changelog/releases/odoc/2019-03-08-odoc-1.4.0.md similarity index 100% rename from data/changelog/odoc/2019-03-08-odoc-1.4.0.md rename to data/changelog/releases/odoc/2019-03-08-odoc-1.4.0.md diff --git a/data/changelog/odoc/2019-06-25-odoc-1.4.1.md b/data/changelog/releases/odoc/2019-06-25-odoc-1.4.1.md similarity index 100% rename from data/changelog/odoc/2019-06-25-odoc-1.4.1.md rename to data/changelog/releases/odoc/2019-06-25-odoc-1.4.1.md diff --git a/data/changelog/odoc/2019-09-19-odoc-1.4.2.md b/data/changelog/releases/odoc/2019-09-19-odoc-1.4.2.md similarity index 100% rename from data/changelog/odoc/2019-09-19-odoc-1.4.2.md rename to data/changelog/releases/odoc/2019-09-19-odoc-1.4.2.md diff --git a/data/changelog/odoc/2020-02-08-odoc-1.5.0.md b/data/changelog/releases/odoc/2020-02-08-odoc-1.5.0.md similarity index 100% rename from data/changelog/odoc/2020-02-08-odoc-1.5.0.md rename to data/changelog/releases/odoc/2020-02-08-odoc-1.5.0.md diff --git a/data/changelog/odoc/2020-06-15-odoc-1.5.1.md b/data/changelog/releases/odoc/2020-06-15-odoc-1.5.1.md similarity index 100% rename from data/changelog/odoc/2020-06-15-odoc-1.5.1.md rename to data/changelog/releases/odoc/2020-06-15-odoc-1.5.1.md diff --git a/data/changelog/odoc/2020-11-12-odoc-1.5.2.md b/data/changelog/releases/odoc/2020-11-12-odoc-1.5.2.md similarity index 100% rename from data/changelog/odoc/2020-11-12-odoc-1.5.2.md rename to data/changelog/releases/odoc/2020-11-12-odoc-1.5.2.md diff --git a/data/changelog/odoc/2021-07-10-odoc-1.5.3.md b/data/changelog/releases/odoc/2021-07-10-odoc-1.5.3.md similarity index 100% rename from data/changelog/odoc/2021-07-10-odoc-1.5.3.md rename to data/changelog/releases/odoc/2021-07-10-odoc-1.5.3.md diff --git a/data/changelog/odoc/2021-10-06-odoc-2.0.0.md b/data/changelog/releases/odoc/2021-10-06-odoc-2.0.0.md similarity index 100% rename from data/changelog/odoc/2021-10-06-odoc-2.0.0.md rename to data/changelog/releases/odoc/2021-10-06-odoc-2.0.0.md diff --git a/data/changelog/odoc/2021-11-30-odoc-2.0.1.md b/data/changelog/releases/odoc/2021-11-30-odoc-2.0.1.md similarity index 100% rename from data/changelog/odoc/2021-11-30-odoc-2.0.1.md rename to data/changelog/releases/odoc/2021-11-30-odoc-2.0.1.md diff --git a/data/changelog/odoc/2021-12-02-odoc-2.0.2.md b/data/changelog/releases/odoc/2021-12-02-odoc-2.0.2.md similarity index 100% rename from data/changelog/odoc/2021-12-02-odoc-2.0.2.md rename to data/changelog/releases/odoc/2021-12-02-odoc-2.0.2.md diff --git a/data/changelog/odoc/2022-02-08-odoc-2.1.0.md b/data/changelog/releases/odoc/2022-02-08-odoc-2.1.0.md similarity index 100% rename from data/changelog/odoc/2022-02-08-odoc-2.1.0.md rename to data/changelog/releases/odoc/2022-02-08-odoc-2.1.0.md diff --git a/data/changelog/odoc/2022-07-06-odoc-2.1.1.md b/data/changelog/releases/odoc/2022-07-06-odoc-2.1.1.md similarity index 100% rename from data/changelog/odoc/2022-07-06-odoc-2.1.1.md rename to data/changelog/releases/odoc/2022-07-06-odoc-2.1.1.md diff --git a/data/changelog/odoc/2022-12-13-odoc-2.2.0.md b/data/changelog/releases/odoc/2022-12-13-odoc-2.2.0.md similarity index 100% rename from data/changelog/odoc/2022-12-13-odoc-2.2.0.md rename to data/changelog/releases/odoc/2022-12-13-odoc-2.2.0.md diff --git a/data/changelog/odoc/2023-08-08-odoc-2.2.1.md b/data/changelog/releases/odoc/2023-08-08-odoc-2.2.1.md similarity index 100% rename from data/changelog/odoc/2023-08-08-odoc-2.2.1.md rename to data/changelog/releases/odoc/2023-08-08-odoc-2.2.1.md diff --git a/data/changelog/odoc/2023-10-02-odoc-2.3.0.md b/data/changelog/releases/odoc/2023-10-02-odoc-2.3.0.md similarity index 100% rename from data/changelog/odoc/2023-10-02-odoc-2.3.0.md rename to data/changelog/releases/odoc/2023-10-02-odoc-2.3.0.md diff --git a/data/changelog/odoc/2023-10-30-odoc-2.3.1.md b/data/changelog/releases/odoc/2023-10-30-odoc-2.3.1.md similarity index 100% rename from data/changelog/odoc/2023-10-30-odoc-2.3.1.md rename to data/changelog/releases/odoc/2023-10-30-odoc-2.3.1.md diff --git a/data/changelog/odoc/2023-12-14-odoc-2.4.0.md b/data/changelog/releases/odoc/2023-12-14-odoc-2.4.0.md similarity index 100% rename from data/changelog/odoc/2023-12-14-odoc-2.4.0.md rename to data/changelog/releases/odoc/2023-12-14-odoc-2.4.0.md diff --git a/data/changelog/odoc/2024-01-24-odoc-2.4.1.md b/data/changelog/releases/odoc/2024-01-24-odoc-2.4.1.md similarity index 100% rename from data/changelog/odoc/2024-01-24-odoc-2.4.1.md rename to data/changelog/releases/odoc/2024-01-24-odoc-2.4.1.md diff --git a/data/changelog/odoc/2024-04-30-odoc-2.4.2.md b/data/changelog/releases/odoc/2024-04-30-odoc-2.4.2.md similarity index 100% rename from data/changelog/odoc/2024-04-30-odoc-2.4.2.md rename to data/changelog/releases/odoc/2024-04-30-odoc-2.4.2.md diff --git a/data/changelog/releases/odoc/2025-03-20-odoc-3.0.0.md b/data/changelog/releases/odoc/2025-03-20-odoc-3.0.0.md new file mode 100644 index 0000000000..7d59d1e4fd --- /dev/null +++ b/data/changelog/releases/odoc/2025-03-20-odoc-3.0.0.md @@ -0,0 +1,65 @@ +--- +title: Odoc 3.0 +tags: [odoc, platform] +changelog: | + ### Added + + - Add png, pdf and jpeg image support to the latex backend by Octachron · Pull Request #1297 · ocaml/odoc · GitHub + - Add header field to the json output by panglesd · Pull Request #1314 · ocaml/odoc · GitHub + - Extract code blocks by name by panglesd · Pull Request #1326 · ocaml/odoc · GitHub + + ### Changed + + - Fix suppress_warnings parameter by jonludlam · Pull Request #1304 · ocaml/odoc · GitHub + - Fix suppress_warnings parameter by jonludlam · Pull Request #1304 · ocaml/odoc · GitHub + - Disable warnings coming from linking implementations by jonludlam · Pull Request #1319 · ocaml/odoc · GitHub + - Driver compile warnings by jonludlam · Pull Request #1323 · ocaml/odoc · GitHub + - Fix "box model" for code blocks by panglesd · Pull Request #1317 · ocaml/odoc · GitHub + - Store raw content of code blocks in parser's AST by panglesd · Pull Request #1325 · ocaml/odoc · GitHub + + ### Fixed + + - Fix suppress_warnings parameter by jonludlam · Pull Request #1304 · ocaml/odoc · GitHub + - Don't backtrace on invalid input in compile-deps by jonludlam · Pull Request #1313 · ocaml/odoc · GitHub + - Fix indentation bug with verbatim in tags by jonludlam · Pull Request #1312 · ocaml/odoc · GitHub + - Driver: Check for missing/unknown opam packages by jonludlam · Pull Request #1311 · ocaml/odoc · GitHub + - Fix suppress_warnings parameter by jonludlam · Pull Request #1304 · ocaml/odoc · GitHub + - Further fixes for virtual libraries by jonludlam · Pull Request #1309 · ocaml/odoc · GitHub + - Fix issue #610 - `odoc html-fragment` not producing headings correctly by jonludlam · Pull Request #1306 · ocaml/odoc · GitHub + - Fix classify when there are archives sharing modules by jonludlam · Pull Request #1310 · ocaml/odoc · GitHub +--- + +We are delighted to announce the release of Odoc 3! This is a big release with loads of new features and bug fixes, and we encourage everyone to install it and try the new features! + +This release has been cooking for a long time - it’s been more than a year since odoc 2.4 landed, and a huge amount of work has gone into this. Thanks to the many others who contributed, either by code or by comments: @juloo, @panglesd, @EmileTrotignon, @gpetiot, @trefis, @sabine, @dbuenzli, @yawaramin, and more. + +Here is an overview of some major new features: + +- Search by type! Our detective sherlodoc will find your lost value given its type. +- Odoc 3 features a global sidebar, allowing you to discover all documentation pages +- The generated documentation include the source code. You can jump from any item in the documentation straight to its rendered source; no matter how much of OCaml’s complex module system you are using. +- You can now add images to your documentation, as well as video and audio files +Hierarchical documentation pages allow you to structure your documentation better +- Reference items from other packages! With the ability to use cross-package links in your documentation, the generated documentation is now truly connected. +- The build dependencies are friendlier with incremental build systems, allowing better shared build caches + +With this release we’re including a driver that makes use of all the exciting new features of odoc. This driver has been used to create the [docs site for the various odoc tools](https://ocaml.github.io/odoc/). However, Dune does not yet support odoc 3 since the Dune rules for running odoc via Dune need to be rewritten to reflect the odoc's new CLI and the new incremental build related capabilities odoc 3 brings. + +Until Dune supports odoc 3, here is how to get started: + +```sh +$ opam install odoc-driver # will install odoc 3 +$ odoc_driver odoc odoc-parser odoc-driver odoc-md sherlodoc --remap +``` + +and point your browser at `_html/index.html`. This example shows `odoc_driver` creating the docs for exactly the 5 packages specified. While doing so, it will remap links to other packages to instead link to their documentation page hosted on [ocaml.org](https://ocaml.org) (see ["Remapping dependencies" in the odoc documentation](https://ocaml.github.io/odoc/odoc-driver/index.html#remapping-dependencies)). + +If you try the above command, you'll note something interesting, and hopefully this will encourage you to run `odoc_driver` on your own packages before you release them, as then you'll be able to avoid slightly embarrassing post-release fixes like [this one](https://github.com/ocaml/odoc/pull/1333) 😬 + + + \ No newline at end of file diff --git a/data/changelog/omp/2017-03-21-omp-0.6.md b/data/changelog/releases/omp/2017-03-21-omp-0.6.md similarity index 100% rename from data/changelog/omp/2017-03-21-omp-0.6.md rename to data/changelog/releases/omp/2017-03-21-omp-0.6.md diff --git a/data/changelog/omp/2017-03-22-omp-0.7.md b/data/changelog/releases/omp/2017-03-22-omp-0.7.md similarity index 100% rename from data/changelog/omp/2017-03-22-omp-0.7.md rename to data/changelog/releases/omp/2017-03-22-omp-0.7.md diff --git a/data/changelog/omp/2017-04-17-omp-1.0.md b/data/changelog/releases/omp/2017-04-17-omp-1.0.md similarity index 100% rename from data/changelog/omp/2017-04-17-omp-1.0.md rename to data/changelog/releases/omp/2017-04-17-omp-1.0.md diff --git a/data/changelog/omp/2017-06-06-omp-1.0.1.md b/data/changelog/releases/omp/2017-06-06-omp-1.0.1.md similarity index 100% rename from data/changelog/omp/2017-06-06-omp-1.0.1.md rename to data/changelog/releases/omp/2017-06-06-omp-1.0.1.md diff --git a/data/changelog/omp/2017-08-01-omp-1.0.2.md b/data/changelog/releases/omp/2017-08-01-omp-1.0.2.md similarity index 100% rename from data/changelog/omp/2017-08-01-omp-1.0.2.md rename to data/changelog/releases/omp/2017-08-01-omp-1.0.2.md diff --git a/data/changelog/omp/2017-08-14-omp-1.0.3.md b/data/changelog/releases/omp/2017-08-14-omp-1.0.3.md similarity index 100% rename from data/changelog/omp/2017-08-14-omp-1.0.3.md rename to data/changelog/releases/omp/2017-08-14-omp-1.0.3.md diff --git a/data/changelog/omp/2017-08-23-omp-1.0.4.md b/data/changelog/releases/omp/2017-08-23-omp-1.0.4.md similarity index 100% rename from data/changelog/omp/2017-08-23-omp-1.0.4.md rename to data/changelog/releases/omp/2017-08-23-omp-1.0.4.md diff --git a/data/changelog/omp/2017-10-02-omp-1.0.5.md b/data/changelog/releases/omp/2017-10-02-omp-1.0.5.md similarity index 100% rename from data/changelog/omp/2017-10-02-omp-1.0.5.md rename to data/changelog/releases/omp/2017-10-02-omp-1.0.5.md diff --git a/data/changelog/omp/2017-10-13-omp-1.0.6.md b/data/changelog/releases/omp/2017-10-13-omp-1.0.6.md similarity index 100% rename from data/changelog/omp/2017-10-13-omp-1.0.6.md rename to data/changelog/releases/omp/2017-10-13-omp-1.0.6.md diff --git a/data/changelog/omp/2017-10-31-omp-1.0.7.md b/data/changelog/releases/omp/2017-10-31-omp-1.0.7.md similarity index 100% rename from data/changelog/omp/2017-10-31-omp-1.0.7.md rename to data/changelog/releases/omp/2017-10-31-omp-1.0.7.md diff --git a/data/changelog/omp/2018-03-15-omp-1.0.8.md b/data/changelog/releases/omp/2018-03-15-omp-1.0.8.md similarity index 100% rename from data/changelog/omp/2018-03-15-omp-1.0.8.md rename to data/changelog/releases/omp/2018-03-15-omp-1.0.8.md diff --git a/data/changelog/omp/2018-03-21-omp-1.0.9.md b/data/changelog/releases/omp/2018-03-21-omp-1.0.9.md similarity index 100% rename from data/changelog/omp/2018-03-21-omp-1.0.9.md rename to data/changelog/releases/omp/2018-03-21-omp-1.0.9.md diff --git a/data/changelog/omp/2018-04-22-omp-1.0.10.md b/data/changelog/releases/omp/2018-04-22-omp-1.0.10.md similarity index 100% rename from data/changelog/omp/2018-04-22-omp-1.0.10.md rename to data/changelog/releases/omp/2018-04-22-omp-1.0.10.md diff --git a/data/changelog/omp/2018-06-07-omp-1.0.11.md b/data/changelog/releases/omp/2018-06-07-omp-1.0.11.md similarity index 100% rename from data/changelog/omp/2018-06-07-omp-1.0.11.md rename to data/changelog/releases/omp/2018-06-07-omp-1.0.11.md diff --git a/data/changelog/omp/2018-09-20-omp-1.1.0.md b/data/changelog/releases/omp/2018-09-20-omp-1.1.0.md similarity index 100% rename from data/changelog/omp/2018-09-20-omp-1.1.0.md rename to data/changelog/releases/omp/2018-09-20-omp-1.1.0.md diff --git a/data/changelog/omp/2019-01-11-omp-1.2.0.md b/data/changelog/releases/omp/2019-01-11-omp-1.2.0.md similarity index 100% rename from data/changelog/omp/2019-01-11-omp-1.2.0.md rename to data/changelog/releases/omp/2019-01-11-omp-1.2.0.md diff --git a/data/changelog/omp/2019-05-09-omp-1.3.0.md b/data/changelog/releases/omp/2019-05-09-omp-1.3.0.md similarity index 100% rename from data/changelog/omp/2019-05-09-omp-1.3.0.md rename to data/changelog/releases/omp/2019-05-09-omp-1.3.0.md diff --git a/data/changelog/omp/2019-05-22-omp-1.3.1.md b/data/changelog/releases/omp/2019-05-22-omp-1.3.1.md similarity index 100% rename from data/changelog/omp/2019-05-22-omp-1.3.1.md rename to data/changelog/releases/omp/2019-05-22-omp-1.3.1.md diff --git a/data/changelog/omp/2019-07-04-omp-1.4.0.md b/data/changelog/releases/omp/2019-07-04-omp-1.4.0.md similarity index 100% rename from data/changelog/omp/2019-07-04-omp-1.4.0.md rename to data/changelog/releases/omp/2019-07-04-omp-1.4.0.md diff --git a/data/changelog/omp/2019-11-19-omp-1.5.0.md b/data/changelog/releases/omp/2019-11-19-omp-1.5.0.md similarity index 100% rename from data/changelog/omp/2019-11-19-omp-1.5.0.md rename to data/changelog/releases/omp/2019-11-19-omp-1.5.0.md diff --git a/data/changelog/omp/2020-02-13-omp-1.6.0.md b/data/changelog/releases/omp/2020-02-13-omp-1.6.0.md similarity index 100% rename from data/changelog/omp/2020-02-13-omp-1.6.0.md rename to data/changelog/releases/omp/2020-02-13-omp-1.6.0.md diff --git a/data/changelog/omp/2020-04-15-omp-1.7.1.md b/data/changelog/releases/omp/2020-04-15-omp-1.7.1.md similarity index 100% rename from data/changelog/omp/2020-04-15-omp-1.7.1.md rename to data/changelog/releases/omp/2020-04-15-omp-1.7.1.md diff --git a/data/changelog/omp/2020-04-20-omp-1.7.2.md b/data/changelog/releases/omp/2020-04-20-omp-1.7.2.md similarity index 100% rename from data/changelog/omp/2020-04-20-omp-1.7.2.md rename to data/changelog/releases/omp/2020-04-20-omp-1.7.2.md diff --git a/data/changelog/omp/2020-05-07-omp-1.7.3.md b/data/changelog/releases/omp/2020-05-07-omp-1.7.3.md similarity index 100% rename from data/changelog/omp/2020-05-07-omp-1.7.3.md rename to data/changelog/releases/omp/2020-05-07-omp-1.7.3.md diff --git a/data/changelog/omp/2020-08-12-omp-2.0.0.md b/data/changelog/releases/omp/2020-08-12-omp-2.0.0.md similarity index 100% rename from data/changelog/omp/2020-08-12-omp-2.0.0.md rename to data/changelog/releases/omp/2020-08-12-omp-2.0.0.md diff --git a/data/changelog/omp/2020-10-22-omp-2.1.0.md b/data/changelog/releases/omp/2020-10-22-omp-2.1.0.md similarity index 100% rename from data/changelog/omp/2020-10-22-omp-2.1.0.md rename to data/changelog/releases/omp/2020-10-22-omp-2.1.0.md diff --git a/data/changelog/omp/2020-10-23-omp-1.8.0.md b/data/changelog/releases/omp/2020-10-23-omp-1.8.0.md similarity index 100% rename from data/changelog/omp/2020-10-23-omp-1.8.0.md rename to data/changelog/releases/omp/2020-10-23-omp-1.8.0.md diff --git a/data/changelog/omp/2021-06-22-omp-2.2.0.md b/data/changelog/releases/omp/2021-06-22-omp-2.2.0.md similarity index 100% rename from data/changelog/omp/2021-06-22-omp-2.2.0.md rename to data/changelog/releases/omp/2021-06-22-omp-2.2.0.md diff --git a/data/changelog/omp/2021-12-07-omp-2.3.0.md b/data/changelog/releases/omp/2021-12-07-omp-2.3.0.md similarity index 100% rename from data/changelog/omp/2021-12-07-omp-2.3.0.md rename to data/changelog/releases/omp/2021-12-07-omp-2.3.0.md diff --git a/data/changelog/omp/2022-06-17-omp-2.4.0.md b/data/changelog/releases/omp/2022-06-17-omp-2.4.0.md similarity index 100% rename from data/changelog/omp/2022-06-17-omp-2.4.0.md rename to data/changelog/releases/omp/2022-06-17-omp-2.4.0.md diff --git a/data/changelog/omp/2023-10-23-omp-deprecation.md b/data/changelog/releases/omp/2023-10-23-omp-deprecation.md similarity index 100% rename from data/changelog/omp/2023-10-23-omp-deprecation.md rename to data/changelog/releases/omp/2023-10-23-omp-deprecation.md diff --git a/data/changelog/opam-publish/2014-11-18-opam-publish-0.2.0.md b/data/changelog/releases/opam-publish/2014-11-18-opam-publish-0.2.0.md similarity index 100% rename from data/changelog/opam-publish/2014-11-18-opam-publish-0.2.0.md rename to data/changelog/releases/opam-publish/2014-11-18-opam-publish-0.2.0.md diff --git a/data/changelog/opam-publish/2014-12-10-opam-publish-0.2.1.md b/data/changelog/releases/opam-publish/2014-12-10-opam-publish-0.2.1.md similarity index 100% rename from data/changelog/opam-publish/2014-12-10-opam-publish-0.2.1.md rename to data/changelog/releases/opam-publish/2014-12-10-opam-publish-0.2.1.md diff --git a/data/changelog/opam-publish/2015-07-18-opam-publish-0.3.0.md b/data/changelog/releases/opam-publish/2015-07-18-opam-publish-0.3.0.md similarity index 100% rename from data/changelog/opam-publish/2015-07-18-opam-publish-0.3.0.md rename to data/changelog/releases/opam-publish/2015-07-18-opam-publish-0.3.0.md diff --git a/data/changelog/opam-publish/2017-07-11-opam-publish-0.3.5.md b/data/changelog/releases/opam-publish/2017-07-11-opam-publish-0.3.5.md similarity index 100% rename from data/changelog/opam-publish/2017-07-11-opam-publish-0.3.5.md rename to data/changelog/releases/opam-publish/2017-07-11-opam-publish-0.3.5.md diff --git a/data/changelog/opam-publish/2018-09-19-opam-publish-2.0.0.md b/data/changelog/releases/opam-publish/2018-09-19-opam-publish-2.0.0.md similarity index 100% rename from data/changelog/opam-publish/2018-09-19-opam-publish-2.0.0.md rename to data/changelog/releases/opam-publish/2018-09-19-opam-publish-2.0.0.md diff --git a/data/changelog/opam-publish/2018-10-11-opam-publish-2.0.1.md b/data/changelog/releases/opam-publish/2018-10-11-opam-publish-2.0.1.md similarity index 100% rename from data/changelog/opam-publish/2018-10-11-opam-publish-2.0.1.md rename to data/changelog/releases/opam-publish/2018-10-11-opam-publish-2.0.1.md diff --git a/data/changelog/opam-publish/2019-12-09-opam-publish-2.0.2.md b/data/changelog/releases/opam-publish/2019-12-09-opam-publish-2.0.2.md similarity index 100% rename from data/changelog/opam-publish/2019-12-09-opam-publish-2.0.2.md rename to data/changelog/releases/opam-publish/2019-12-09-opam-publish-2.0.2.md diff --git a/data/changelog/opam-publish/2021-01-13-opam-publish-2.0.3.md b/data/changelog/releases/opam-publish/2021-01-13-opam-publish-2.0.3.md similarity index 100% rename from data/changelog/opam-publish/2021-01-13-opam-publish-2.0.3.md rename to data/changelog/releases/opam-publish/2021-01-13-opam-publish-2.0.3.md diff --git a/data/changelog/opam-publish/2021-07-01-opam-publish-2.1.0.md b/data/changelog/releases/opam-publish/2021-07-01-opam-publish-2.1.0.md similarity index 100% rename from data/changelog/opam-publish/2021-07-01-opam-publish-2.1.0.md rename to data/changelog/releases/opam-publish/2021-07-01-opam-publish-2.1.0.md diff --git a/data/changelog/opam-publish/2022-12-14-opam-publish-2.2.0.md b/data/changelog/releases/opam-publish/2022-12-14-opam-publish-2.2.0.md similarity index 100% rename from data/changelog/opam-publish/2022-12-14-opam-publish-2.2.0.md rename to data/changelog/releases/opam-publish/2022-12-14-opam-publish-2.2.0.md diff --git a/data/changelog/opam-publish/2023-10-30-opam-publish-2.3.0.md b/data/changelog/releases/opam-publish/2023-10-30-opam-publish-2.3.0.md similarity index 100% rename from data/changelog/opam-publish/2023-10-30-opam-publish-2.3.0.md rename to data/changelog/releases/opam-publish/2023-10-30-opam-publish-2.3.0.md diff --git a/data/changelog/opam/2013-03-15-opam-1-0-0-released.md b/data/changelog/releases/opam/2013-03-15-opam-1-0-0-released.md similarity index 100% rename from data/changelog/opam/2013-03-15-opam-1-0-0-released.md rename to data/changelog/releases/opam/2013-03-15-opam-1-0-0-released.md diff --git a/data/changelog/opam/2013-11-08-opam-1-1-0-released.md b/data/changelog/releases/opam/2013-11-08-opam-1-1-0-released.md similarity index 100% rename from data/changelog/opam/2013-11-08-opam-1-1-0-released.md rename to data/changelog/releases/opam/2013-11-08-opam-1-1-0-released.md diff --git a/data/changelog/opam/2014-01-29-opam-1-1-1-released.md b/data/changelog/releases/opam/2014-01-29-opam-1-1-1-released.md similarity index 100% rename from data/changelog/opam/2014-01-29-opam-1-1-1-released.md rename to data/changelog/releases/opam/2014-01-29-opam-1-1-1-released.md diff --git a/data/changelog/opam/2014-08-19-opam-1-2-pin.md b/data/changelog/releases/opam/2014-08-19-opam-1-2-pin.md similarity index 100% rename from data/changelog/opam/2014-08-19-opam-1-2-pin.md rename to data/changelog/releases/opam/2014-08-19-opam-1-2-pin.md diff --git a/data/changelog/opam/2014-10-23-opam-1-2-0-release.md b/data/changelog/releases/opam/2014-10-23-opam-1-2-0-release.md similarity index 100% rename from data/changelog/opam/2014-10-23-opam-1-2-0-release.md rename to data/changelog/releases/opam/2014-10-23-opam-1-2-0-release.md diff --git a/data/changelog/opam/2015-03-18-opam-1-2-1-release.md b/data/changelog/releases/opam/2015-03-18-opam-1-2-1-release.md similarity index 100% rename from data/changelog/opam/2015-03-18-opam-1-2-1-release.md rename to data/changelog/releases/opam/2015-03-18-opam-1-2-1-release.md diff --git a/data/changelog/opam/2015-05-07-opam-1-2-2-release.md b/data/changelog/releases/opam/2015-05-07-opam-1-2-2-release.md similarity index 100% rename from data/changelog/opam/2015-05-07-opam-1-2-2-release.md rename to data/changelog/releases/opam/2015-05-07-opam-1-2-2-release.md diff --git a/data/changelog/opam/2016-11-21-opam-lib-1-3.md b/data/changelog/releases/opam/2016-11-21-opam-lib-1-3.md similarity index 100% rename from data/changelog/opam/2016-11-21-opam-lib-1-3.md rename to data/changelog/releases/opam/2016-11-21-opam-lib-1-3.md diff --git a/data/changelog/opam/2018-09-18-opam-2-0-0.md b/data/changelog/releases/opam/2018-09-18-opam-2-0-0.md similarity index 100% rename from data/changelog/opam/2018-09-18-opam-2-0-0.md rename to data/changelog/releases/opam/2018-09-18-opam-2-0-0.md diff --git a/data/changelog/opam/2018-10-24-opam-2-0-1.md b/data/changelog/releases/opam/2018-10-24-opam-2-0-1.md similarity index 100% rename from data/changelog/opam/2018-10-24-opam-2-0-1.md rename to data/changelog/releases/opam/2018-10-24-opam-2-0-1.md diff --git a/data/changelog/opam/2018-12-12-opam-2-0-2.md b/data/changelog/releases/opam/2018-12-12-opam-2-0-2.md similarity index 100% rename from data/changelog/opam/2018-12-12-opam-2-0-2.md rename to data/changelog/releases/opam/2018-12-12-opam-2-0-2.md diff --git a/data/changelog/opam/2019-01-28-opam-2-0-3.md b/data/changelog/releases/opam/2019-01-28-opam-2-0-3.md similarity index 100% rename from data/changelog/opam/2019-01-28-opam-2-0-3.md rename to data/changelog/releases/opam/2019-01-28-opam-2-0-3.md diff --git a/data/changelog/opam/2019-04-10-opam-2-0-4.md b/data/changelog/releases/opam/2019-04-10-opam-2-0-4.md similarity index 100% rename from data/changelog/opam/2019-04-10-opam-2-0-4.md rename to data/changelog/releases/opam/2019-04-10-opam-2-0-4.md diff --git a/data/changelog/opam/2019-07-11-opam-2-0-5.md b/data/changelog/releases/opam/2019-07-11-opam-2-0-5.md similarity index 100% rename from data/changelog/opam/2019-07-11-opam-2-0-5.md rename to data/changelog/releases/opam/2019-07-11-opam-2-0-5.md diff --git a/data/changelog/opam/2020-01-16-opam-2-0-6.md b/data/changelog/releases/opam/2020-01-16-opam-2-0-6.md similarity index 100% rename from data/changelog/opam/2020-01-16-opam-2-0-6.md rename to data/changelog/releases/opam/2020-01-16-opam-2-0-6.md diff --git a/data/changelog/opam/2020-04-21-opam-2-0-7.md b/data/changelog/releases/opam/2020-04-21-opam-2-0-7.md similarity index 100% rename from data/changelog/opam/2020-04-21-opam-2-0-7.md rename to data/changelog/releases/opam/2020-04-21-opam-2-0-7.md diff --git a/data/changelog/opam/2021-02-08-opam-2-0-8.md b/data/changelog/releases/opam/2021-02-08-opam-2-0-8.md similarity index 100% rename from data/changelog/opam/2021-02-08-opam-2-0-8.md rename to data/changelog/releases/opam/2021-02-08-opam-2-0-8.md diff --git a/data/changelog/opam/2021-08-03-opam-2-0-9.md b/data/changelog/releases/opam/2021-08-03-opam-2-0-9.md similarity index 100% rename from data/changelog/opam/2021-08-03-opam-2-0-9.md rename to data/changelog/releases/opam/2021-08-03-opam-2-0-9.md diff --git a/data/changelog/opam/2021-08-04-opam-2-1-0.md b/data/changelog/releases/opam/2021-08-04-opam-2-1-0.md similarity index 100% rename from data/changelog/opam/2021-08-04-opam-2-1-0.md rename to data/changelog/releases/opam/2021-08-04-opam-2-1-0.md diff --git a/data/changelog/opam/2021-11-15-opam-2-0-10.md b/data/changelog/releases/opam/2021-11-15-opam-2-0-10.md similarity index 100% rename from data/changelog/opam/2021-11-15-opam-2-0-10.md rename to data/changelog/releases/opam/2021-11-15-opam-2-0-10.md diff --git a/data/changelog/opam/2021-11-15-opam-2-1-1.md b/data/changelog/releases/opam/2021-11-15-opam-2-1-1.md similarity index 100% rename from data/changelog/opam/2021-11-15-opam-2-1-1.md rename to data/changelog/releases/opam/2021-11-15-opam-2-1-1.md diff --git a/data/changelog/opam/2021-12-08-opam-2-1-2.md b/data/changelog/releases/opam/2021-12-08-opam-2-1-2.md similarity index 100% rename from data/changelog/opam/2021-12-08-opam-2-1-2.md rename to data/changelog/releases/opam/2021-12-08-opam-2-1-2.md diff --git a/data/changelog/opam/2022-12-15-opam-2-1-4.md b/data/changelog/releases/opam/2022-12-15-opam-2-1-4.md similarity index 100% rename from data/changelog/opam/2022-12-15-opam-2-1-4.md rename to data/changelog/releases/opam/2022-12-15-opam-2-1-4.md diff --git a/data/changelog/opam/2023-05-31-opam-2-1-5.md b/data/changelog/releases/opam/2023-05-31-opam-2-1-5.md similarity index 100% rename from data/changelog/opam/2023-05-31-opam-2-1-5.md rename to data/changelog/releases/opam/2023-05-31-opam-2-1-5.md diff --git a/data/changelog/opam/2024-05-22-opam-2-1-6.md b/data/changelog/releases/opam/2024-05-22-opam-2-1-6.md similarity index 100% rename from data/changelog/opam/2024-05-22-opam-2-1-6.md rename to data/changelog/releases/opam/2024-05-22-opam-2-1-6.md diff --git a/data/changelog/opam/2024-07-01-opam-2-2-0.md b/data/changelog/releases/opam/2024-07-01-opam-2-2-0.md similarity index 98% rename from data/changelog/opam/2024-07-01-opam-2-2-0.md rename to data/changelog/releases/opam/2024-07-01-opam-2-2-0.md index 0ac013e64c..a0b77b9ba6 100644 --- a/data/changelog/opam/2024-07-01-opam-2-2-0.md +++ b/data/changelog/releases/opam/2024-07-01-opam-2-2-0.md @@ -49,7 +49,7 @@ support! A big thank you is due to Andreas Hauptmann ([@fdopen](https://github.c whose [WODI](https://github.com/fdopen/godi-repo) and [OCaml for Windows](https://fdopen.github.io/opam-repository-mingw/) projects were for many years the principal downstream way to obtain OCaml on Windows, Jun Furuse ([@camlspotter](https://github.com/camlspotter)) whose -[initial experimentation with OPAM from Cygwin](https://inbox.vuxu.org/caml-list/CAAoLEWsQK7=qER66Uixx5pq4wLExXovrQWM6b69_fyMmjYFiZA@mail.gmail.com/) +[initial experimentation with OPAM from Cygwin](https://inbox.ci.dev/caml-list/CAAoLEWsQK7=qER66Uixx5pq4wLExXovrQWM6b69_fyMmjYFiZA@mail.gmail.com/) formed the basis of opam-repository-mingw, and, most recently, Jonah Beckford ([@jonahbeckford](https://github.com/JonahBeckford)) whose [DkML](https://diskuv.com/dkmlbook/) distribution kept - and keeps - a full diff --git a/data/changelog/opam/2024-08-22-opam-2-2-1.md b/data/changelog/releases/opam/2024-08-22-opam-2-2-1.md similarity index 100% rename from data/changelog/opam/2024-08-22-opam-2-2-1.md rename to data/changelog/releases/opam/2024-08-22-opam-2-2-1.md diff --git a/data/changelog/opam/2024-11-13-opam-2-3-0.md b/data/changelog/releases/opam/2024-11-13-opam-2-3-0.md similarity index 100% rename from data/changelog/opam/2024-11-13-opam-2-3-0.md rename to data/changelog/releases/opam/2024-11-13-opam-2-3-0.md diff --git a/data/changelog/ppxlib/2018-03-19-ppxlib-0.1.0.md b/data/changelog/releases/ppxlib/2018-03-19-ppxlib-0.1.0.md similarity index 100% rename from data/changelog/ppxlib/2018-03-19-ppxlib-0.1.0.md rename to data/changelog/releases/ppxlib/2018-03-19-ppxlib-0.1.0.md diff --git a/data/changelog/ppxlib/2018-03-22-ppxlib-0.2.0.md b/data/changelog/releases/ppxlib/2018-03-22-ppxlib-0.2.0.md similarity index 100% rename from data/changelog/ppxlib/2018-03-22-ppxlib-0.2.0.md rename to data/changelog/releases/ppxlib/2018-03-22-ppxlib-0.2.0.md diff --git a/data/changelog/ppxlib/2018-04-28-ppxlib-0.3.0.md b/data/changelog/releases/ppxlib/2018-04-28-ppxlib-0.3.0.md similarity index 100% rename from data/changelog/ppxlib/2018-04-28-ppxlib-0.3.0.md rename to data/changelog/releases/ppxlib/2018-04-28-ppxlib-0.3.0.md diff --git a/data/changelog/ppxlib/2018-06-04-ppxlib-0.2.1.md b/data/changelog/releases/ppxlib/2018-06-04-ppxlib-0.2.1.md similarity index 100% rename from data/changelog/ppxlib/2018-06-04-ppxlib-0.2.1.md rename to data/changelog/releases/ppxlib/2018-06-04-ppxlib-0.2.1.md diff --git a/data/changelog/ppxlib/2018-09-17-ppxlib-0.2.2.md b/data/changelog/releases/ppxlib/2018-09-17-ppxlib-0.2.2.md similarity index 100% rename from data/changelog/ppxlib/2018-09-17-ppxlib-0.2.2.md rename to data/changelog/releases/ppxlib/2018-09-17-ppxlib-0.2.2.md diff --git a/data/changelog/ppxlib/2018-09-20-ppxlib-0.3.1.md b/data/changelog/releases/ppxlib/2018-09-20-ppxlib-0.3.1.md similarity index 100% rename from data/changelog/ppxlib/2018-09-20-ppxlib-0.3.1.md rename to data/changelog/releases/ppxlib/2018-09-20-ppxlib-0.3.1.md diff --git a/data/changelog/ppxlib/2018-12-16-ppxlib-0.4.0.md b/data/changelog/releases/ppxlib/2018-12-16-ppxlib-0.4.0.md similarity index 100% rename from data/changelog/ppxlib/2018-12-16-ppxlib-0.4.0.md rename to data/changelog/releases/ppxlib/2018-12-16-ppxlib-0.4.0.md diff --git a/data/changelog/ppxlib/2019-01-10-ppxlib-0.5.0.md b/data/changelog/releases/ppxlib/2019-01-10-ppxlib-0.5.0.md similarity index 100% rename from data/changelog/ppxlib/2019-01-10-ppxlib-0.5.0.md rename to data/changelog/releases/ppxlib/2019-01-10-ppxlib-0.5.0.md diff --git a/data/changelog/ppxlib/2019-04-17-ppxlib-0.6.0.md b/data/changelog/releases/ppxlib/2019-04-17-ppxlib-0.6.0.md similarity index 100% rename from data/changelog/ppxlib/2019-04-17-ppxlib-0.6.0.md rename to data/changelog/releases/ppxlib/2019-04-17-ppxlib-0.6.0.md diff --git a/data/changelog/ppxlib/2019-05-28-ppxlib-0.7.0.md b/data/changelog/releases/ppxlib/2019-05-28-ppxlib-0.7.0.md similarity index 100% rename from data/changelog/ppxlib/2019-05-28-ppxlib-0.7.0.md rename to data/changelog/releases/ppxlib/2019-05-28-ppxlib-0.7.0.md diff --git a/data/changelog/ppxlib/2019-05-28-ppxlib-0.8.0.md b/data/changelog/releases/ppxlib/2019-05-28-ppxlib-0.8.0.md similarity index 100% rename from data/changelog/ppxlib/2019-05-28-ppxlib-0.8.0.md rename to data/changelog/releases/ppxlib/2019-05-28-ppxlib-0.8.0.md diff --git a/data/changelog/ppxlib/2019-07-23-ppxlib-0.8.1.md b/data/changelog/releases/ppxlib/2019-07-23-ppxlib-0.8.1.md similarity index 100% rename from data/changelog/ppxlib/2019-07-23-ppxlib-0.8.1.md rename to data/changelog/releases/ppxlib/2019-07-23-ppxlib-0.8.1.md diff --git a/data/changelog/ppxlib/2019-08-02-ppxlib-0.9.0.md b/data/changelog/releases/ppxlib/2019-08-02-ppxlib-0.9.0.md similarity index 100% rename from data/changelog/ppxlib/2019-08-02-ppxlib-0.9.0.md rename to data/changelog/releases/ppxlib/2019-08-02-ppxlib-0.9.0.md diff --git a/data/changelog/ppxlib/2019-11-29-ppxlib-0.10.0.md b/data/changelog/releases/ppxlib/2019-11-29-ppxlib-0.10.0.md similarity index 100% rename from data/changelog/ppxlib/2019-11-29-ppxlib-0.10.0.md rename to data/changelog/releases/ppxlib/2019-11-29-ppxlib-0.10.0.md diff --git a/data/changelog/ppxlib/2020-01-07-ppxlib-0.11.0.md b/data/changelog/releases/ppxlib/2020-01-07-ppxlib-0.11.0.md similarity index 100% rename from data/changelog/ppxlib/2020-01-07-ppxlib-0.11.0.md rename to data/changelog/releases/ppxlib/2020-01-07-ppxlib-0.11.0.md diff --git a/data/changelog/ppxlib/2020-01-07-ppxlib-0.12.0.md b/data/changelog/releases/ppxlib/2020-01-07-ppxlib-0.12.0.md similarity index 100% rename from data/changelog/ppxlib/2020-01-07-ppxlib-0.12.0.md rename to data/changelog/releases/ppxlib/2020-01-07-ppxlib-0.12.0.md diff --git a/data/changelog/ppxlib/2020-04-15-ppxlib-0.13.0.md b/data/changelog/releases/ppxlib/2020-04-15-ppxlib-0.13.0.md similarity index 100% rename from data/changelog/ppxlib/2020-04-15-ppxlib-0.13.0.md rename to data/changelog/releases/ppxlib/2020-04-15-ppxlib-0.13.0.md diff --git a/data/changelog/ppxlib/2020-07-08-ppxlib-0.14.0.md b/data/changelog/releases/ppxlib/2020-07-08-ppxlib-0.14.0.md similarity index 100% rename from data/changelog/ppxlib/2020-07-08-ppxlib-0.14.0.md rename to data/changelog/releases/ppxlib/2020-07-08-ppxlib-0.14.0.md diff --git a/data/changelog/ppxlib/2020-08-06-ppxlib-0.15.0.md b/data/changelog/releases/ppxlib/2020-08-06-ppxlib-0.15.0.md similarity index 100% rename from data/changelog/ppxlib/2020-08-06-ppxlib-0.15.0.md rename to data/changelog/releases/ppxlib/2020-08-06-ppxlib-0.15.0.md diff --git a/data/changelog/ppxlib/2020-08-19-ppxlib-0.16.0.md b/data/changelog/releases/ppxlib/2020-08-19-ppxlib-0.16.0.md similarity index 100% rename from data/changelog/ppxlib/2020-08-19-ppxlib-0.16.0.md rename to data/changelog/releases/ppxlib/2020-08-19-ppxlib-0.16.0.md diff --git a/data/changelog/ppxlib/2020-09-17-ppxlib-0.17.0.md b/data/changelog/releases/ppxlib/2020-09-17-ppxlib-0.17.0.md similarity index 100% rename from data/changelog/ppxlib/2020-09-17-ppxlib-0.17.0.md rename to data/changelog/releases/ppxlib/2020-09-17-ppxlib-0.17.0.md diff --git a/data/changelog/ppxlib/2020-10-09-ppxlib-0.18.0.md b/data/changelog/releases/ppxlib/2020-10-09-ppxlib-0.18.0.md similarity index 100% rename from data/changelog/ppxlib/2020-10-09-ppxlib-0.18.0.md rename to data/changelog/releases/ppxlib/2020-10-09-ppxlib-0.18.0.md diff --git a/data/changelog/ppxlib/2020-10-23-ppxlib-0.19.0.md b/data/changelog/releases/ppxlib/2020-10-23-ppxlib-0.19.0.md similarity index 100% rename from data/changelog/ppxlib/2020-10-23-ppxlib-0.19.0.md rename to data/changelog/releases/ppxlib/2020-10-23-ppxlib-0.19.0.md diff --git a/data/changelog/ppxlib/2020-11-16-ppxlib-0.20.0.md b/data/changelog/releases/ppxlib/2020-11-16-ppxlib-0.20.0.md similarity index 100% rename from data/changelog/ppxlib/2020-11-16-ppxlib-0.20.0.md rename to data/changelog/releases/ppxlib/2020-11-16-ppxlib-0.20.0.md diff --git a/data/changelog/ppxlib/2021-01-22-ppxlib-0.21.0.md b/data/changelog/releases/ppxlib/2021-01-22-ppxlib-0.21.0.md similarity index 100% rename from data/changelog/ppxlib/2021-01-22-ppxlib-0.21.0.md rename to data/changelog/releases/ppxlib/2021-01-22-ppxlib-0.21.0.md diff --git a/data/changelog/ppxlib/2021-02-06-ppxlib-0.22.0.md b/data/changelog/releases/ppxlib/2021-02-06-ppxlib-0.22.0.md similarity index 100% rename from data/changelog/ppxlib/2021-02-06-ppxlib-0.22.0.md rename to data/changelog/releases/ppxlib/2021-02-06-ppxlib-0.22.0.md diff --git a/data/changelog/ppxlib/2021-06-10-ppxlib-0.21.1.md b/data/changelog/releases/ppxlib/2021-06-10-ppxlib-0.21.1.md similarity index 100% rename from data/changelog/ppxlib/2021-06-10-ppxlib-0.21.1.md rename to data/changelog/releases/ppxlib/2021-06-10-ppxlib-0.21.1.md diff --git a/data/changelog/ppxlib/2021-06-10-ppxlib-0.22.1.md b/data/changelog/releases/ppxlib/2021-06-10-ppxlib-0.22.1.md similarity index 100% rename from data/changelog/ppxlib/2021-06-10-ppxlib-0.22.1.md rename to data/changelog/releases/ppxlib/2021-06-10-ppxlib-0.22.1.md diff --git a/data/changelog/ppxlib/2021-06-24-ppxlib-0.22.2.md b/data/changelog/releases/ppxlib/2021-06-24-ppxlib-0.22.2.md similarity index 100% rename from data/changelog/ppxlib/2021-06-24-ppxlib-0.22.2.md rename to data/changelog/releases/ppxlib/2021-06-24-ppxlib-0.22.2.md diff --git a/data/changelog/ppxlib/2021-09-06-ppxlib-0.23.0.md b/data/changelog/releases/ppxlib/2021-09-06-ppxlib-0.23.0.md similarity index 100% rename from data/changelog/ppxlib/2021-09-06-ppxlib-0.23.0.md rename to data/changelog/releases/ppxlib/2021-09-06-ppxlib-0.23.0.md diff --git a/data/changelog/ppxlib/2021-12-10-ppxlib-0.24.0.md b/data/changelog/releases/ppxlib/2021-12-10-ppxlib-0.24.0.md similarity index 100% rename from data/changelog/ppxlib/2021-12-10-ppxlib-0.24.0.md rename to data/changelog/releases/ppxlib/2021-12-10-ppxlib-0.24.0.md diff --git a/data/changelog/ppxlib/2022-03-03-ppxlib-0.25.0.md b/data/changelog/releases/ppxlib/2022-03-03-ppxlib-0.25.0.md similarity index 100% rename from data/changelog/ppxlib/2022-03-03-ppxlib-0.25.0.md rename to data/changelog/releases/ppxlib/2022-03-03-ppxlib-0.25.0.md diff --git a/data/changelog/ppxlib/2022-03-25-ppxlib-0.26.0.md b/data/changelog/releases/ppxlib/2022-03-25-ppxlib-0.26.0.md similarity index 100% rename from data/changelog/ppxlib/2022-03-25-ppxlib-0.26.0.md rename to data/changelog/releases/ppxlib/2022-03-25-ppxlib-0.26.0.md diff --git a/data/changelog/ppxlib/2022-06-15-ppxlib-0.27.0.md b/data/changelog/releases/ppxlib/2022-06-15-ppxlib-0.27.0.md similarity index 100% rename from data/changelog/ppxlib/2022-06-15-ppxlib-0.27.0.md rename to data/changelog/releases/ppxlib/2022-06-15-ppxlib-0.27.0.md diff --git a/data/changelog/ppxlib/2022-06-17-ppxlib-0.25.1.md b/data/changelog/releases/ppxlib/2022-06-17-ppxlib-0.25.1.md similarity index 100% rename from data/changelog/ppxlib/2022-06-17-ppxlib-0.25.1.md rename to data/changelog/releases/ppxlib/2022-06-17-ppxlib-0.25.1.md diff --git a/data/changelog/ppxlib/2022-10-06-ppxlib-0.28.0.md b/data/changelog/releases/ppxlib/2022-10-06-ppxlib-0.28.0.md similarity index 100% rename from data/changelog/ppxlib/2022-10-06-ppxlib-0.28.0.md rename to data/changelog/releases/ppxlib/2022-10-06-ppxlib-0.28.0.md diff --git a/data/changelog/ppxlib/2023-02-13-ppxlib-0.29.0.md b/data/changelog/releases/ppxlib/2023-02-13-ppxlib-0.29.0.md similarity index 100% rename from data/changelog/ppxlib/2023-02-13-ppxlib-0.29.0.md rename to data/changelog/releases/ppxlib/2023-02-13-ppxlib-0.29.0.md diff --git a/data/changelog/ppxlib/2023-02-14-ppxlib-0.29.1.md b/data/changelog/releases/ppxlib/2023-02-14-ppxlib-0.29.1.md similarity index 100% rename from data/changelog/ppxlib/2023-02-14-ppxlib-0.29.1.md rename to data/changelog/releases/ppxlib/2023-02-14-ppxlib-0.29.1.md diff --git a/data/changelog/ppxlib/2023-06-20-ppxlib-0.30.0.md b/data/changelog/releases/ppxlib/2023-06-20-ppxlib-0.30.0.md similarity index 100% rename from data/changelog/ppxlib/2023-06-20-ppxlib-0.30.0.md rename to data/changelog/releases/ppxlib/2023-06-20-ppxlib-0.30.0.md diff --git a/data/changelog/ppxlib/2023-10-05-ppxlib-0.31.0.md b/data/changelog/releases/ppxlib/2023-10-05-ppxlib-0.31.0.md similarity index 100% rename from data/changelog/ppxlib/2023-10-05-ppxlib-0.31.0.md rename to data/changelog/releases/ppxlib/2023-10-05-ppxlib-0.31.0.md diff --git a/data/changelog/ppxlib/2024-02-07-ppxlib-0.32.0.md b/data/changelog/releases/ppxlib/2024-02-07-ppxlib-0.32.0.md similarity index 100% rename from data/changelog/ppxlib/2024-02-07-ppxlib-0.32.0.md rename to data/changelog/releases/ppxlib/2024-02-07-ppxlib-0.32.0.md diff --git a/data/changelog/ppxlib/2024-04-30-ppxlib-0.32.1.md b/data/changelog/releases/ppxlib/2024-04-30-ppxlib-0.32.1.md similarity index 100% rename from data/changelog/ppxlib/2024-04-30-ppxlib-0.32.1.md rename to data/changelog/releases/ppxlib/2024-04-30-ppxlib-0.32.1.md diff --git a/data/changelog/ppxlib/2024-07-25-ppxlib-0.33.0.md b/data/changelog/releases/ppxlib/2024-07-25-ppxlib-0.33.0.md similarity index 100% rename from data/changelog/ppxlib/2024-07-25-ppxlib-0.33.0.md rename to data/changelog/releases/ppxlib/2024-07-25-ppxlib-0.33.0.md diff --git a/data/changelog/releases/ppxlib/2025-01-08-ppxlib-0.34.0.md b/data/changelog/releases/ppxlib/2025-01-08-ppxlib-0.34.0.md new file mode 100644 index 0000000000..d3f968ea41 --- /dev/null +++ b/data/changelog/releases/ppxlib/2025-01-08-ppxlib-0.34.0.md @@ -0,0 +1,90 @@ +--- +title: Ppxlib 0.34.0 +tags: [ppxlib, platform] +changelog: | + - Add initial OCaml 5.3 support (#487, @NathanReb, @hhugo, @nojb) + + - Initialise OCaml 5.3's lexer with the `keywords` setting from `OCAMLPARAM` or + the new `-keywords` driver's CLI option to allow the standalone ppx driver to + process old packages using `effect` as an identifier + (#535, @dra27, @NathanReb) + + - Add `Pprintast.binding`, `longident` and `payload` (#542, @mattiasdrp) + + - Fix `deriving_inline` round-trip check so that it works with 5.01 <-> 5.02 + migrations (#519, @NathanReb) + + - Add ppxlib's AST pretty-printing utilities in `Ppxlib.Pp_ast` and + a `ppxlib-pp-ast` executable in a new separate `ppxlib-tools` package + (#517, #525, #537, @NathanReb) + + - Change `-dparsetree` from a sexp output to a pretty printed AST, closer + to what the compiler's `-dparsetree` is. + (#530, @NathanReb) + + - Add Parsetree documentation comments to `Ast_builder` functions (#518, @patricoferris) + + - Support class type declarations in derivers with the new, optional arguments + `{str,sig}_class_type_decl` in `Deriving.add` (#538, @patricoferris) +--- +We’re happy to announce that we just released ppxlib.0.34.0. + +The full patch notes are available on the release page over here. + +The main features are OCaml 5.3 compatibility, new AST pretty-printing utilities and the ppxlib-tools package, support for [@@deriving ...] on class types and the addition of missing Pprintast entry points. + +## Changes summary + +### 5.3 compatibility + +ppxlib.0.34.0 is the first official ppxlib release that’s compatible with the new 5.3 compiler. + +The ppxlib driver now also comes with a `-keywords` CLI option, similar to the compiler’s that allow you to compile and preprocess with the 5.3 compiler code that uses effect as an identifier. This is pretty niche but it’s there should you need it. + +Please note that means you can use ppx-es with a 5.3 compiler but not that ppx-es can consume/produce 5.3 language features. We’re currently working on a fix allowing you to use the effect syntax in files that require preprocessing as it’s not possible with 0.34.0. The fix should be released in the next few days as 0.34.1. + +### AST pretty-printing + +We added a new `Pp_ast` module that allows you to pretty print AST fragments. + +The only way ppxlib would print ASTs before were as S-expressions. In practice we found that it was not always helpful and wanted a more readable and human friendly way of displaying the AST. + +The default output of those printer is a simplified version of the AST to keep things clear and avoid cluttering the output with information that is not always useful. For example, if you run `Ppxlib.Pp_ast.Default.expression` on the AST for `x + 2`, you’ll get the following: + +``` +Pexp_apply + ( Pexp_ident (Lident "+") + , [ ( Nolabel, Pexp_ident (Lident "x")) + ; ( Nolabel, Pexp_constant (Pconst_integer ( "2", None))) + ] + ) +``` +The alert reader will note that there are no locations or attributes and that the expression record layer is omitted here. + +You can of course configure the printer to display more information if you need to. + +We’ve been using these new printers internally to debug migration code and they have been a huge help so we hope they will make working with ppxlib easier for you too. + +In addition to this new module, we also added a command line utility called `ppxlib-pp-ast` to pretty print ASTs from source files, source code fragments or even marshalled AST files. It is very similar to the old `ppx_tools`’s `dumpast`. + +Note that it will print ppxlib’s internal AST after it’s been migrated from the installed compiler’s version. This is something that we could not simply achieve with OCaml’s own `-dparsetree`. + +This should be a useful tool for debugging ppx related bugs or learning about the AST and we hope ppx authors and users will like it. + +### Other changes + +As mentioned above, we also added some missing `Pprintast`* entries such as `binding`, `longident` and `payload`. + +It is now possible to use `[@@deriving ...]` on class type declarations and therefore to write derivers for class types. + +\*: *To the confused readers: Pprintast is entirely different from Pp_ast mentioned above as it prints the source code corresponding to a given AST.* + +## Special thanks + +We wanted to thank our external contributors for this release: @hhugo, @nojb and @dra27 for their help on the 5.3 compat and @mattiasdrp for bringing the Pprintast module up to speed. + +Special thanks as well to @pedrobslisboa who started integrating their excellent ppx-by-example into ppxlib’s documentation. + +Finally, I’d also like to thank the OCaml Software Foundation who’s been funding all my work on ppxlib and made this release possible! + +Happy preprocessing to you all! diff --git a/data/changelog/releases/ppxlib/2025-02-04-ppxlib-0.35.0.md b/data/changelog/releases/ppxlib/2025-02-04-ppxlib-0.35.0.md new file mode 100644 index 0000000000..9a2925e4af --- /dev/null +++ b/data/changelog/releases/ppxlib/2025-02-04-ppxlib-0.35.0.md @@ -0,0 +1,22 @@ +--- +title: Ppxlib 0.35.0 +tags: [ppxlib, platform] +changelog: | + + - Allow use of effect syntax in preprocessed files without causing migration + failures. (#552, @hhugo, @NathanReb) + + - Remove support for compilers older than 4.08 (#556, @NathanReb) + + - Add a `--use-compiler-pp` flag to the standalone driver. This flag + can be set when the driver outputs source code to make it use the compiler's + `Pprintast` instead of ppxlib's. + (#555, @NathanReb) +--- +We are happy to announce the release of ppxlib.0.35.0! + +The main feature of this release is improved support for OCaml 5.3, allowing ppx users to have ppx rewriters operate on files with the new effect syntax. + +Note that ppx-es and the effect syntax can cohabit but it is possible that ppx rewriters will error out if they encounter effect syntax node in their extension's payload or in the items they generate code from. + +This feature also comes with a new `--use-compiler-pp` driver flag. This flag is required to preserve the effect syntax when the ppxlib driver outputs source code instead of marshalled AST. Note that the vast majority of users won't need to use this flag but it can come in handy in some more advanced use cases. diff --git a/data/changelog/releases/ppxlib/2025-03-05-ppxlib-0.36.0.md b/data/changelog/releases/ppxlib/2025-03-05-ppxlib-0.36.0.md new file mode 100644 index 0000000000..90a050acec --- /dev/null +++ b/data/changelog/releases/ppxlib/2025-03-05-ppxlib-0.36.0.md @@ -0,0 +1,30 @@ +--- +title: Ppxlib 0.36.0 +tags: [ppxlib, platform] +changelog: | + + - Change `Location.none` to match the compiler's `Location.none` as of OCaml + 4.08. This fixes a bug in `loc_of_attribute` (#540, @ncik-roberts, @patricoferris) + + - Bump ppxlib's AST to 5.2.0 (#514, @patricoferris) + + - Add the `[@@@expand_inline]` transformation and support for floating attribute context + free transformations. (#560, @jaymody) + + - Add a `-raise-embedded-errors` flag to the driver. Setting this flag raises the first + `ocaml.error` embedded in the final AST. + + - Export `Ast_pattern.fail`. (#563, @ceastlund) + + - Make `Ast_traverse.sexp_of` more concise, and add a test. (#561, @ceastlund) + +--- +We are happy to announce the release of ppxlib.0.36.0! + +With this release, the internal AST that ppxlib targets has been bumped to the AST of OCaml 5.2. +Ppx authors can now use features from OCaml 5.2. Ppxlib still supports any OCaml compiler +after and including 4.08.0. + +Many ppxes will be broken by changes made to the representation of functions. Authors are encouraged +to read [the upgrade guide](https://github.com/ocaml-ppx/ppxlib/wiki/Upgrading-to-ppxlib-0.36.0). + diff --git a/data/changelog/utop/2013-11-21-utop-1.2.1.md b/data/changelog/releases/utop/2013-11-21-utop-1.2.1.md similarity index 100% rename from data/changelog/utop/2013-11-21-utop-1.2.1.md rename to data/changelog/releases/utop/2013-11-21-utop-1.2.1.md diff --git a/data/changelog/utop/2013-11-21-utop-1.3.0.md b/data/changelog/releases/utop/2013-11-21-utop-1.3.0.md similarity index 100% rename from data/changelog/utop/2013-11-21-utop-1.3.0.md rename to data/changelog/releases/utop/2013-11-21-utop-1.3.0.md diff --git a/data/changelog/utop/2013-11-21-utop-1.4.0.md b/data/changelog/releases/utop/2013-11-21-utop-1.4.0.md similarity index 100% rename from data/changelog/utop/2013-11-21-utop-1.4.0.md rename to data/changelog/releases/utop/2013-11-21-utop-1.4.0.md diff --git a/data/changelog/utop/2013-11-21-utop-1.5.md b/data/changelog/releases/utop/2013-11-21-utop-1.5.md similarity index 100% rename from data/changelog/utop/2013-11-21-utop-1.5.md rename to data/changelog/releases/utop/2013-11-21-utop-1.5.md diff --git a/data/changelog/utop/2013-11-21-utop-1.6.md b/data/changelog/releases/utop/2013-11-21-utop-1.6.md similarity index 100% rename from data/changelog/utop/2013-11-21-utop-1.6.md rename to data/changelog/releases/utop/2013-11-21-utop-1.6.md diff --git a/data/changelog/utop/2013-11-21-utop-1.7.md b/data/changelog/releases/utop/2013-11-21-utop-1.7.md similarity index 100% rename from data/changelog/utop/2013-11-21-utop-1.7.md rename to data/changelog/releases/utop/2013-11-21-utop-1.7.md diff --git a/data/changelog/utop/2013-11-21-utop-1.8.md b/data/changelog/releases/utop/2013-11-21-utop-1.8.md similarity index 100% rename from data/changelog/utop/2013-11-21-utop-1.8.md rename to data/changelog/releases/utop/2013-11-21-utop-1.8.md diff --git a/data/changelog/utop/2013-11-27-utop-1.9.md b/data/changelog/releases/utop/2013-11-27-utop-1.9.md similarity index 100% rename from data/changelog/utop/2013-11-27-utop-1.9.md rename to data/changelog/releases/utop/2013-11-27-utop-1.9.md diff --git a/data/changelog/utop/2013-12-11-utop-1.10.md b/data/changelog/releases/utop/2013-12-11-utop-1.10.md similarity index 100% rename from data/changelog/utop/2013-12-11-utop-1.10.md rename to data/changelog/releases/utop/2013-12-11-utop-1.10.md diff --git a/data/changelog/utop/2014-02-11-utop-1.11.md b/data/changelog/releases/utop/2014-02-11-utop-1.11.md similarity index 100% rename from data/changelog/utop/2014-02-11-utop-1.11.md rename to data/changelog/releases/utop/2014-02-11-utop-1.11.md diff --git a/data/changelog/utop/2014-04-22-utop-1.12.md b/data/changelog/releases/utop/2014-04-22-utop-1.12.md similarity index 100% rename from data/changelog/utop/2014-04-22-utop-1.12.md rename to data/changelog/releases/utop/2014-04-22-utop-1.12.md diff --git a/data/changelog/utop/2014-07-09-utop-1.14.md b/data/changelog/releases/utop/2014-07-09-utop-1.14.md similarity index 100% rename from data/changelog/utop/2014-07-09-utop-1.14.md rename to data/changelog/releases/utop/2014-07-09-utop-1.14.md diff --git a/data/changelog/utop/2014-08-30-utop-1.15.md b/data/changelog/releases/utop/2014-08-30-utop-1.15.md similarity index 100% rename from data/changelog/utop/2014-08-30-utop-1.15.md rename to data/changelog/releases/utop/2014-08-30-utop-1.15.md diff --git a/data/changelog/utop/2014-10-23-utop-1.16.md b/data/changelog/releases/utop/2014-10-23-utop-1.16.md similarity index 100% rename from data/changelog/utop/2014-10-23-utop-1.16.md rename to data/changelog/releases/utop/2014-10-23-utop-1.16.md diff --git a/data/changelog/utop/2014-12-12-utop-1.17.md b/data/changelog/releases/utop/2014-12-12-utop-1.17.md similarity index 100% rename from data/changelog/utop/2014-12-12-utop-1.17.md rename to data/changelog/releases/utop/2014-12-12-utop-1.17.md diff --git a/data/changelog/utop/2015-06-23-utop-1.18.md b/data/changelog/releases/utop/2015-06-23-utop-1.18.md similarity index 100% rename from data/changelog/utop/2015-06-23-utop-1.18.md rename to data/changelog/releases/utop/2015-06-23-utop-1.18.md diff --git a/data/changelog/utop/2015-11-03-utop-1.18.1.md b/data/changelog/releases/utop/2015-11-03-utop-1.18.1.md similarity index 100% rename from data/changelog/utop/2015-11-03-utop-1.18.1.md rename to data/changelog/releases/utop/2015-11-03-utop-1.18.1.md diff --git a/data/changelog/utop/2016-03-03-utop-1.18.2.md b/data/changelog/releases/utop/2016-03-03-utop-1.18.2.md similarity index 100% rename from data/changelog/utop/2016-03-03-utop-1.18.2.md rename to data/changelog/releases/utop/2016-03-03-utop-1.18.2.md diff --git a/data/changelog/utop/2016-04-09-utop-1.19.md b/data/changelog/releases/utop/2016-04-09-utop-1.19.md similarity index 100% rename from data/changelog/utop/2016-04-09-utop-1.19.md rename to data/changelog/releases/utop/2016-04-09-utop-1.19.md diff --git a/data/changelog/utop/2016-04-18-utop-1.19.1.md b/data/changelog/releases/utop/2016-04-18-utop-1.19.1.md similarity index 100% rename from data/changelog/utop/2016-04-18-utop-1.19.1.md rename to data/changelog/releases/utop/2016-04-18-utop-1.19.1.md diff --git a/data/changelog/utop/2016-04-25-utop-1.19.2.md b/data/changelog/releases/utop/2016-04-25-utop-1.19.2.md similarity index 100% rename from data/changelog/utop/2016-04-25-utop-1.19.2.md rename to data/changelog/releases/utop/2016-04-25-utop-1.19.2.md diff --git a/data/changelog/utop/2016-08-15-utop-1.19.3.md b/data/changelog/releases/utop/2016-08-15-utop-1.19.3.md similarity index 100% rename from data/changelog/utop/2016-08-15-utop-1.19.3.md rename to data/changelog/releases/utop/2016-08-15-utop-1.19.3.md diff --git a/data/changelog/utop/2017-05-26-utop-2.0.0.md b/data/changelog/releases/utop/2017-05-26-utop-2.0.0.md similarity index 100% rename from data/changelog/utop/2017-05-26-utop-2.0.0.md rename to data/changelog/releases/utop/2017-05-26-utop-2.0.0.md diff --git a/data/changelog/utop/2017-05-30-utop-2.0.1.md b/data/changelog/releases/utop/2017-05-30-utop-2.0.1.md similarity index 100% rename from data/changelog/utop/2017-05-30-utop-2.0.1.md rename to data/changelog/releases/utop/2017-05-30-utop-2.0.1.md diff --git a/data/changelog/utop/2017-11-07-utop-2.0.2.md b/data/changelog/releases/utop/2017-11-07-utop-2.0.2.md similarity index 100% rename from data/changelog/utop/2017-11-07-utop-2.0.2.md rename to data/changelog/releases/utop/2017-11-07-utop-2.0.2.md diff --git a/data/changelog/utop/2018-02-28-utop-2.1.0.md b/data/changelog/releases/utop/2018-02-28-utop-2.1.0.md similarity index 100% rename from data/changelog/utop/2018-02-28-utop-2.1.0.md rename to data/changelog/releases/utop/2018-02-28-utop-2.1.0.md diff --git a/data/changelog/utop/2018-07-15-utop-2.2.0.md b/data/changelog/releases/utop/2018-07-15-utop-2.2.0.md similarity index 100% rename from data/changelog/utop/2018-07-15-utop-2.2.0.md rename to data/changelog/releases/utop/2018-07-15-utop-2.2.0.md diff --git a/data/changelog/utop/2019-01-31-utop-2.3.0.md b/data/changelog/releases/utop/2019-01-31-utop-2.3.0.md similarity index 100% rename from data/changelog/utop/2019-01-31-utop-2.3.0.md rename to data/changelog/releases/utop/2019-01-31-utop-2.3.0.md diff --git a/data/changelog/utop/2019-05-27-utop-2.4.0.md b/data/changelog/releases/utop/2019-05-27-utop-2.4.0.md similarity index 100% rename from data/changelog/utop/2019-05-27-utop-2.4.0.md rename to data/changelog/releases/utop/2019-05-27-utop-2.4.0.md diff --git a/data/changelog/utop/2019-08-11-utop-2.4.1.md b/data/changelog/releases/utop/2019-08-11-utop-2.4.1.md similarity index 100% rename from data/changelog/utop/2019-08-11-utop-2.4.1.md rename to data/changelog/releases/utop/2019-08-11-utop-2.4.1.md diff --git a/data/changelog/utop/2019-09-18-utop-2.4.2.md b/data/changelog/releases/utop/2019-09-18-utop-2.4.2.md similarity index 100% rename from data/changelog/utop/2019-09-18-utop-2.4.2.md rename to data/changelog/releases/utop/2019-09-18-utop-2.4.2.md diff --git a/data/changelog/utop/2019-12-31-utop-2.4.3.md b/data/changelog/releases/utop/2019-12-31-utop-2.4.3.md similarity index 100% rename from data/changelog/utop/2019-12-31-utop-2.4.3.md rename to data/changelog/releases/utop/2019-12-31-utop-2.4.3.md diff --git a/data/changelog/utop/2020-04-28-utop-2.5.0.md b/data/changelog/releases/utop/2020-04-28-utop-2.5.0.md similarity index 100% rename from data/changelog/utop/2020-04-28-utop-2.5.0.md rename to data/changelog/releases/utop/2020-04-28-utop-2.5.0.md diff --git a/data/changelog/utop/2020-05-31-utop-2.6.0.md b/data/changelog/releases/utop/2020-05-31-utop-2.6.0.md similarity index 100% rename from data/changelog/utop/2020-05-31-utop-2.6.0.md rename to data/changelog/releases/utop/2020-05-31-utop-2.6.0.md diff --git a/data/changelog/utop/2021-01-06-utop-2.7.0.md b/data/changelog/releases/utop/2021-01-06-utop-2.7.0.md similarity index 100% rename from data/changelog/utop/2021-01-06-utop-2.7.0.md rename to data/changelog/releases/utop/2021-01-06-utop-2.7.0.md diff --git a/data/changelog/utop/2021-06-18-utop-2.8.0.md b/data/changelog/releases/utop/2021-06-18-utop-2.8.0.md similarity index 100% rename from data/changelog/utop/2021-06-18-utop-2.8.0.md rename to data/changelog/releases/utop/2021-06-18-utop-2.8.0.md diff --git a/data/changelog/utop/2021-12-09-utop-2.9.0.md b/data/changelog/releases/utop/2021-12-09-utop-2.9.0.md similarity index 100% rename from data/changelog/utop/2021-12-09-utop-2.9.0.md rename to data/changelog/releases/utop/2021-12-09-utop-2.9.0.md diff --git a/data/changelog/utop/2022-03-28-utop-2.9.1.md b/data/changelog/releases/utop/2022-03-28-utop-2.9.1.md similarity index 100% rename from data/changelog/utop/2022-03-28-utop-2.9.1.md rename to data/changelog/releases/utop/2022-03-28-utop-2.9.1.md diff --git a/data/changelog/utop/2022-06-17-utop-2.9.2.md b/data/changelog/releases/utop/2022-06-17-utop-2.9.2.md similarity index 100% rename from data/changelog/utop/2022-06-17-utop-2.9.2.md rename to data/changelog/releases/utop/2022-06-17-utop-2.9.2.md diff --git a/data/changelog/utop/2022-07-06-utop-2.10.0.md b/data/changelog/releases/utop/2022-07-06-utop-2.10.0.md similarity index 100% rename from data/changelog/utop/2022-07-06-utop-2.10.0.md rename to data/changelog/releases/utop/2022-07-06-utop-2.10.0.md diff --git a/data/changelog/utop/2023-01-06-utop-2.11.0.md b/data/changelog/releases/utop/2023-01-06-utop-2.11.0.md similarity index 100% rename from data/changelog/utop/2023-01-06-utop-2.11.0.md rename to data/changelog/releases/utop/2023-01-06-utop-2.11.0.md diff --git a/data/changelog/utop/2023-04-17-utop-2.12.0.md b/data/changelog/releases/utop/2023-04-17-utop-2.12.0.md similarity index 100% rename from data/changelog/utop/2023-04-17-utop-2.12.0.md rename to data/changelog/releases/utop/2023-04-17-utop-2.12.0.md diff --git a/data/changelog/utop/2023-04-24-utop-2.12.1.md b/data/changelog/releases/utop/2023-04-24-utop-2.12.1.md similarity index 100% rename from data/changelog/utop/2023-04-24-utop-2.12.1.md rename to data/changelog/releases/utop/2023-04-24-utop-2.12.1.md diff --git a/data/changelog/utop/2023-07-04-utop-2.13.0.md b/data/changelog/releases/utop/2023-07-04-utop-2.13.0.md similarity index 100% rename from data/changelog/utop/2023-07-04-utop-2.13.0.md rename to data/changelog/releases/utop/2023-07-04-utop-2.13.0.md diff --git a/data/changelog/utop/2023-07-11-utop-2.13.1.md b/data/changelog/releases/utop/2023-07-11-utop-2.13.1.md similarity index 100% rename from data/changelog/utop/2023-07-11-utop-2.13.1.md rename to data/changelog/releases/utop/2023-07-11-utop-2.13.1.md diff --git a/data/changelog/utop/2024-02-27-utop-2.14.0.md b/data/changelog/releases/utop/2024-02-27-utop-2.14.0.md similarity index 100% rename from data/changelog/utop/2024-02-27-utop-2.14.0.md rename to data/changelog/releases/utop/2024-02-27-utop-2.14.0.md diff --git a/data/conferences/2012-ocaml-users-and-developers-workshop.md b/data/conferences/2012-ocaml-users-and-developers-workshop.md index ec05bb1362..530da0738b 100644 --- a/data/conferences/2012-ocaml-users-and-developers-workshop.md +++ b/data/conferences/2012-ocaml-users-and-developers-workshop.md @@ -19,31 +19,31 @@ presentations: - title: Presenting Core authors: - Yaron Minsky - video: https://watch.ocaml.org/videos/watch/3159e115-948e-4f67-9d45-403bef003c35 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/3159e115-948e-4f67-9d45-403bef003c35 - title: 'Ocsigen/Eliom: The state of the art, and the prospects' authors: - Benedikt Becker - Vincent Balat - video: https://watch.ocaml.org/videos/watch/d010b30f-61d5-4d70-b10a-518a7a6e1e3f + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/d010b30f-61d5-4d70-b10a-518a7a6e1e3f - title: Experiments in Generic Programming authors: - Pierre Chambart - Grégoire Henry - video: https://watch.ocaml.org/videos/watch/5ae26b10-9a5d-4395-89c6-a2e28e68d206 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/5ae26b10-9a5d-4395-89c6-a2e28e68d206 - title: Async authors: - Mark Shinwell - David House - video: https://watch.ocaml.org/videos/watch/8f50211a-1210-4849-a940-ea6e0bd1e022 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/8f50211a-1210-4849-a940-ea6e0bd1e022 - title: OCamlCC -- Raising Low-Level Bytecode to High-Level C authors: - Michel Mauny - Benoit Vaugon - video: https://watch.ocaml.org/videos/watch/c31ec9fa-7c65-46f5-bbc9-77c6ac87bf0b + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/c31ec9fa-7c65-46f5-bbc9-77c6ac87bf0b - title: The State of OCaml authors: - Xavier Leroy - video: https://watch.ocaml.org/videos/watch/b04b10c1-b924-4f58-8aa9-4527dcc11d8a + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/b04b10c1-b924-4f58-8aa9-4527dcc11d8a - title: 'OCamlPro: promoting OCaml use in industry' authors: - Fabrice le Fessant @@ -51,51 +51,51 @@ presentations: - title: Towards an OCaml Platform authors: - Yaron Minsky - video: https://watch.ocaml.org/videos/watch/96b1ab00-94a8-4059-aec6-a06a9c73c736 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/96b1ab00-94a8-4059-aec6-a06a9c73c736 - title: 'OPAM: an OCaml Package Manager' authors: - Frederic Tuong - Fabrice le Fessant - Thomas Gazagnaire - video: https://watch.ocaml.org/videos/watch/96b1ab00-94a8-4059-aec6-a06a9c73c736 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/96b1ab00-94a8-4059-aec6-a06a9c73c736 - title: An LLVM Backend for OCaml authors: - Colin Benner - video: https://watch.ocaml.org/videos/watch/3ede0b76-e250-4a43-af42-83c394cf4497 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/3ede0b76-e250-4a43-af42-83c394cf4497 - title: 'DragonKit: an extensible language oriented compiler' authors: - Wojciech Meyer - video: https://watch.ocaml.org/videos/watch/8326a03e-02d5-4b32-8789-b7a76c30cf95 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/8326a03e-02d5-4b32-8789-b7a76c30cf95 - title: Programming the Xen cloud using OCaml authors: - David Scott - Richard Mortier - Anil Madhavapeddy - video: https://watch.ocaml.org/videos/watch/360f8fe3-3268-44da-a0c4-b37c26aa7e36 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/360f8fe3-3268-44da-a0c4-b37c26aa7e36 - title: 'Arakoon: a consistent distributed key value store' authors: - Romain Slootmaekers - Nicolas Trangez - video: https://watch.ocaml.org/videos/watch/5309b701-9def-47a4-8240-8a5b17a70b5a + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/5309b701-9def-47a4-8240-8a5b17a70b5a - title: 'gloc: Metaprogramming WebGL Shaders with OCaml' authors: - David Sheets - video: https://watch.ocaml.org/videos/watch/41ca2c8d-2238-44ca-8744-70f114fbd326 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/41ca2c8d-2238-44ca-8744-70f114fbd326 - title: Real-world debugging in OCaml authors: - Mark Shinwell - video: https://watch.ocaml.org/videos/watch/a8f4cf6b-9971-484b-ab5b-34a16fde1185 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/a8f4cf6b-9971-484b-ab5b-34a16fde1185 - title: OCaml Companion Tools authors: - Xavier Clerc - video: https://watch.ocaml.org/videos/watch/4583b254-82f9-4176-9f39-2bc0bb6a9c22 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/4583b254-82f9-4176-9f39-2bc0bb6a9c22 - title: Study of OCaml programs' memory behavior authors: - Çagdas Bozman - Thomas Gazagnaire - Fabrice Le Fessant - Michel Mauny - video: https://watch.ocaml.org/videos/watch/180ee1ea-6fa8-4dba-aa69-e3901cc3147f + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/180ee1ea-6fa8-4dba-aa69-e3901cc3147f - title: Implementing an interval computation library for OCaml authors: - Jean-Marc Alliot @@ -103,11 +103,11 @@ presentations: - Jean-Baptiste Gotteland - Nicolas Durand - David Gianazza - video: https://watch.ocaml.org/videos/watch/e228951b-f544-4bd6-892a-2aca7e2065f9 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/e228951b-f544-4bd6-892a-2aca7e2065f9 - title: Automatic Analysis of Industrial Robot Programs authors: - Markus Weißmann - video: https://watch.ocaml.org/videos/watch/3cebba55-4032-4de5-93b5-8f3f67c04736 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/3cebba55-4032-4de5-93b5-8f3f67c04736 - title: 'Biocaml: The OCaml Bioinformatics Library' authors: - Ashish Agarwal @@ -115,7 +115,7 @@ presentations: - Philippe Veber - Christophe Troestler - Francois Berenger - video: https://watch.ocaml.org/videos/watch/f9ce30b3-8143-4516-85f1-07c28f6337b2 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/f9ce30b3-8143-4516-85f1-07c28f6337b2 organising_committee: [] program_committee: diff --git a/data/conferences/2013-ocaml-users-and-developers-workshop.md b/data/conferences/2013-ocaml-users-and-developers-workshop.md index 6a05ec5170..936963e38d 100644 --- a/data/conferences/2013-ocaml-users-and-developers-workshop.md +++ b/data/conferences/2013-ocaml-users-and-developers-workshop.md @@ -13,37 +13,38 @@ presentations: - title: Accessing and using weather-related data in OCaml authors: - Hezekiah Carty - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/weather-related-data.pdf - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/guha.pdf + link: ocaml/2013/proposals/weather-related-data.pdf + slides: ocaml/2013/slides/carty.pdf - title: The Frenetic Network Controller authors: - Nate Foster - Arjun Guha - Frenetic Contributors - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/frenetic.pdf - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/guha.pdf + link: ocaml/2013/proposals/frenetic.pdf + slides: ocaml/2013/slides/guha.pdf - title: 'Pfff: PHP Program analysis at Facebook' authors: - Yoann Padioleau link: https://github.com/facebook/pfff/wiki/Main - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/padioleau.pdf + slides: ocaml/2013/slides/padioleau.pdf - title: The design of the wxOCaml library authors: - Fabrice Le Fessant - link: + link: ocaml/2013/proposals/wxocaml.pdf + slides: ocaml/2013/slides/lefessant.pdf - title: 'Goji: an Automated Tool for Building High Level OCaml-JavaScript Interfaces' authors: - Benjamin Canou - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/wxocaml.pdf - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/lefessant.pdf + link: ocaml/2013/proposals/goji.pdf + slides: ocaml/2013/slides/canou.pdf - title: 'ctypes: foreign calls in your native language' authors: - Jeremy Yallop - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/ctypes.pdf + link: ocaml/2013/proposals/ctypes.pdf - title: The State of OCaml authors: - Xavier Leroy - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/leroy.pdf + slides: ocaml/2013/slides/leroy.pdf - title: The OCaml Platform v0.1 authors: - Anil Madhavapeddy @@ -53,67 +54,68 @@ presentations: - Philippe Wang - Leo White - Jeremy Yallop - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/platform.pdf - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/madhavapeddy.pdf + link: ocaml/2013/proposals/platform.pdf + slides: ocaml/2013/slides/madhavapeddy.pdf - title: Extensions points for OCaml authors: - Leo White - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/white.pdf + slides: ocaml/2013/slides/white.pdf - title: High-Performance GPGPU Programming with OCaml authors: - Mathias Bourgoin - Emmmanuel Chailloux - Jean-Luc Lamotte - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/gpgpu.pdf - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/bourgoin.pdf + link: ocaml/2013/proposals/gpgpu.pdf + slides: ocaml/2013/slides/bourgoin.pdf - title: Improving OCaml high level optimisations authors: - Pierre Chambart - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/optimizations.pdf - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/chambart.pdf + link: ocaml/2013/proposals/optimizations.pdf + slides: ocaml/2013/slides/chambart.pdf - title: A new implementation of OCaml formats based on GADTs authors: - Benoît Vaugon - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/formats-as-gadts.pdf https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/vaugon.pdf + link: ocaml/2013/proposals/formats-as-gadts.pdf + slides: ocaml/2013/slides/vaugon.pdf - title: Runtime types in OCaml authors: - Grégoire Henry - Jacques Garrigue - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/runtime-types.pdf - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/henry.pdf + link: ocaml/2013/proposals/runtime-types.pdf + slides: ocaml/2013/slides/henry.pdf - title: On variance, injectivity, and abstraction authors: - Jacques Garrigue - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/injectivity.pdf - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/garrigue.pdf + link: ocaml/2013/proposals/injectivity.pdf + slides: ocaml/2013/slides/garrigue.pdf - title: 'Ocamlot: OCaml Online Testing' authors: - David Sheets - Anil Madhavapeddy - Amir Chaudhry - Thomas Gazagnaire - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/ocamlot.pdf - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/sheets.pdf + link: ocaml/2013/proposals/ocamlot.pdf + slides: ocaml/2013/slides/sheets.pdf - title: Merlin, an assistant for editing OCaml code authors: - Frédéric Bour - Thomas Refis - Simon Castellan - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/merlin.pdf + link: ocaml/2013/proposals/merlin.pdf - title: Profiling the Memory Usage of OCaml Applications without Changing their Behavior authors: - Çagdas Bozman - Michel Mauny - Fabrice Le Fessant - Thomas Gazagnaire - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/profiling-memory.pdf - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/bozman.pdf + link: ocaml/2013/proposals/profiling-memory.pdf + slides: ocaml/2013/slides/bozman.pdf - title: 'Core bench: micro-benchmarking for OCaml' authors: - Christopher Hardin - James Roshan - link: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/proposals/core-bench.pdf - slides: https://github.com/ocaml/v2.ocaml.org/blob/master/site/meetings/ocaml/2013/slides/james.pdf + link: ocaml/2013/proposals/core-bench.pdf + slides: ocaml/2013/slides/james.pdf organising_committee: [] program_committee: - name: Mark Shinwell diff --git a/data/conferences/2014-ocaml-users-and-developers-workshop.md b/data/conferences/2014-ocaml-users-and-developers-workshop.md index a437f2132b..27f1965af9 100644 --- a/data/conferences/2014-ocaml-users-and-developers-workshop.md +++ b/data/conferences/2014-ocaml-users-and-developers-workshop.md @@ -30,28 +30,28 @@ presentations: - Stephen Dolan - Leo White - Anil Madhavapeddy - video: https://watch.ocaml.org/videos/watch/490b5363-01b6-45d8-9b7e-c883a20026a1 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/490b5363-01b6-45d8-9b7e-c883a20026a1 - title: Ephemerons meet OCaml GC authors: - François Bobot - video: https://watch.ocaml.org/videos/watch/556c8f75-b456-43a3-b9cb-97ae35b82072 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/556c8f75-b456-43a3-b9cb-97ae35b82072 - title: Introduction to 0install authors: - Thomas Leonard - video: https://watch.ocaml.org/videos/watch/21a21c83-a35d-4c09-b13c-8f060590c45c + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/21a21c83-a35d-4c09-b13c-8f060590c45c - title: Transport Layer Security purely in OCaml authors: - Hannes Mehnert - David Kaloper Meršinjak - video: https://watch.ocaml.org/videos/watch/03721258-b275-4c98-8a0b-9e4606b32fec + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/03721258-b275-4c98-8a0b-9e4606b32fec - title: 'OCamlOScope: a New OCaml API Search' authors: - Jun Furuse - video: https://watch.ocaml.org/videos/watch/c3e3cf25-0fa7-46ad-b0bf-f313bad7142d + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/c3e3cf25-0fa7-46ad-b0bf-f313bad7142d - title: The State of OCaml (invited) authors: - Xavier Leroy - video: https://watch.ocaml.org/videos/watch/11844424-be9b-4427-b3dd-24c3e4ff85a9 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/11844424-be9b-4427-b3dd-24c3e4ff85a9 - title: The OCaml Platform v1.0 authors: - Anil Madhavapeddy @@ -64,22 +64,22 @@ presentations: - Mark Shinwell - Leo White - Jeremy Yallop - video: https://watch.ocaml.org/videos/watch/37eaef0e-d826-4452-bf84-f04244a85ce9 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/37eaef0e-d826-4452-bf84-f04244a85ce9 - title: A Proposal for Non-Intrusive Namespaces in OCaml authors: - Pierrick Couderc - Fabrice Le Fessant - Benjamin Canou - Pierre Chambart - video: https://watch.ocaml.org/videos/watch/ded6e8bb-aebd-4fd2-989f-3f0b2b8efaf3 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/ded6e8bb-aebd-4fd2-989f-3f0b2b8efaf3 - title: Improving Type Error Messages in OCaml authors: - Arthur Charguéraud - video: https://watch.ocaml.org/videos/watch/9fa54aee-6b2f-492f-abbe-51affc07ec24 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/9fa54aee-6b2f-492f-abbe-51affc07ec24 - title: 'Github Pull Requests for OCaml development: a field report' authors: - Gabriel Scherer - video: https://watch.ocaml.org/videos/watch/f0021d24-9104-4672-a363-de5c1c514c2e + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/f0021d24-9104-4672-a363-de5c1c514c2e - title: Irminsule; a branch-consistent distributed library database authors: - Thomas Gazagnaire @@ -90,29 +90,29 @@ presentations: - David Sheets - Gregory Tsipenyuk - Jon Crowcroft - video: https://watch.ocaml.org/videos/watch/5546bb89-93a3-4407-a810-2d437479025f + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/5546bb89-93a3-4407-a810-2d437479025f - title: A Case for Multi-Switch Constraints in OPAM authors: - Fabrice Le Fessant - video: https://watch.ocaml.org/videos/watch/744d4a0b-a44c-4040-853c-6be5223ec43b + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/744d4a0b-a44c-4040-853c-6be5223ec43b - title: 'LibreS3: design, challenges, and steps toward reusable libraries' authors: - Edwin Török - video: https://watch.ocaml.org/videos/watch/c1b00980-3a4f-4222-b539-392815f7954f + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/c1b00980-3a4f-4222-b539-392815f7954f - title: Nullable Type Inference authors: - Michel Mauny - Benoit Vaugon - video: https://watch.ocaml.org/videos/watch/380b1c2e-6298-49fc-88a1-c440ece29c76 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/380b1c2e-6298-49fc-88a1-c440ece29c76 - title: Coq of OCaml authors: - Guillaume Claret - video: https://watch.ocaml.org/videos/watch/fc7201df-ec27-4735-a51d-d3170d390346 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/fc7201df-ec27-4735-a51d-d3170d390346 - title: High Performance Client-Side Web Programming with SPOC and Js of ocaml authors: - Mathias Bourgoin - Emmmanuel Chailloux - video: https://watch.ocaml.org/videos/watch/9e68174a-5c92-41f1-abdf-387a6cca7cf1 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/9e68174a-5c92-41f1-abdf-387a6cca7cf1 - title: Using Preferences to Tame your Package Manager authors: - Roberto Di Cosmo @@ -120,11 +120,11 @@ presentations: - Stefano Zacchiroli - Fabrice Le Fessant - Louis Gesbert - video: https://watch.ocaml.org/videos/watch/43536918-a6e5-4a53-a680-bed527319e31 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/43536918-a6e5-4a53-a680-bed527319e31 - title: Simple, efficient, sound-and-complete combinator parsing for all context-free grammars, using an oracle authors: - Tom Ridge - video: https://watch.ocaml.org/videos/watch/7a0a6d3c-dad0-4fe8-9c35-78cbfbd431d9 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/7a0a6d3c-dad0-4fe8-9c35-78cbfbd431d9 organising_committee: [] program_committee: - name: Esther Baruk diff --git a/data/conferences/2015-ocaml-users-and-developers-workshop.md b/data/conferences/2015-ocaml-users-and-developers-workshop.md index e32199b0de..a32796f59d 100644 --- a/data/conferences/2015-ocaml-users-and-developers-workshop.md +++ b/data/conferences/2015-ocaml-users-and-developers-workshop.md @@ -12,32 +12,32 @@ presentations: authors: - Fabrice Le Fessant - Pierre Chambart - video: https://watch.ocaml.org/videos/watch/e1a22cf8-5522-4c05-a8d4-af445bc73556 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/e1a22cf8-5522-4c05-a8d4-af445bc73556 - title: 'Operf: Benchmarking the OCaml Compiler' authors: - Pierre Chambart - Fabrice Le Fessant - Vincent Bernardoff - video: https://watch.ocaml.org/videos/watch/eb229518-1108-46bd-b8b2-3ce8b886c96f + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/eb229518-1108-46bd-b8b2-3ce8b886c96f - title: 'Core.Time_stamp_counter: A fast high resolution time source' authors: - Roshan James - Christopher Hardin - video: https://watch.ocaml.org/videos/watch/b6c7860d-e6eb-4404-96c3-917b81ee1f98 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/b6c7860d-e6eb-4404-96c3-917b81ee1f98 - title: Specialization of Generic Array Accesses After Inlining authors: - Ryohei Tokuda - Eijiro Sumii - Akinori Abe - video: https://watch.ocaml.org/videos/watch/515689cc-4736-4e1e-9f9f-be363b4551af + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/515689cc-4736-4e1e-9f9f-be363b4551af - title: Inline Assembly in OCaml authors: - Vladimir Brankov - video: https://watch.ocaml.org/videos/watch/736857f3-99d9-46fb-9b4a-92eba42b2672 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/736857f3-99d9-46fb-9b4a-92eba42b2672 - title: The State of OCaml (invited talk) authors: - Xavier Leroy - video: https://watch.ocaml.org/videos/watch/69e486cd-191d-430b-8a41-0be0f806096b + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/69e486cd-191d-430b-8a41-0be0f806096b - title: 'The State of the OCaml Platform: September 2015' authors: - Anil Madhavapeddy @@ -45,7 +45,7 @@ presentations: - Thomas Gazagnaire - Jeremy Yallop - David Sheets - video: https://watch.ocaml.org/videos/watch/0eeab9cb-8984-4323-bad7-0630192c635d + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/0eeab9cb-8984-4323-bad7-0630192c635d - title: Modular macros authors: - Jeremy Yallop diff --git a/data/conferences/2016-ocaml-users-and-developers-workshop.md b/data/conferences/2016-ocaml-users-and-developers-workshop.md index 0428003d71..c73212fc3c 100644 --- a/data/conferences/2016-ocaml-users-and-developers-workshop.md +++ b/data/conferences/2016-ocaml-users-and-developers-workshop.md @@ -14,41 +14,41 @@ presentations: authors: - Hannes Mehnert - Louis Gesbert - video: https://watch.ocaml.org/videos/watch/70fbf7db-28dc-4798-b068-460b5d93df4e + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/70fbf7db-28dc-4798-b068-460b5d93df4e - title: Generic Programming in OCaml authors: - Florent Balestrieri - Michel Mauny - video: https://watch.ocaml.org/videos/watch/0aae98b9-3d0c-427b-af09-802b671dd66e + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/0aae98b9-3d0c-427b-af09-802b671dd66e - title: 'Improving the OCaml Web Stack: Motivations and Progress' authors: - Spiridon Eliopoulos - video: https://watch.ocaml.org/videos/watch/513a2157-6844-4823-bef7-b26f3b635fbe + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/513a2157-6844-4823-bef7-b26f3b635fbe - title: 'Learn OCaml: An Online Learning Center for OCaml' authors: - Benjamin Canou - Grégoire Henry - Çagdas Bozman - Fabrice Le Fessant - video: https://watch.ocaml.org/videos/watch/ea643e64-2393-4c24-9ccf-7216e3ded2ce + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/ea643e64-2393-4c24-9ccf-7216e3ded2ce - title: Lock-free programming for the masses authors: - Kc Sivaramakrishnan - Theo Laurent - video: https://watch.ocaml.org/videos/watch/4435adfc-e97e-42c5-8bb7-1578bd76e42b + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/4435adfc-e97e-42c5-8bb7-1578bd76e42b - title: 'OCaml inside: a drop-in replacement for libtls' authors: - Enguerrand Decorne - Jeremy Yallop - David Kaloper Meršinjak - video: https://watch.ocaml.org/videos/watch/68a11315-f7ca-4c0e-a043-98008694671d + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/68a11315-f7ca-4c0e-a043-98008694671d - title: 'OPAM-builder: Continuous Monitoring of OPAM Repositories' authors: - Fabrice Le Fessant - title: Semantics of the Lambda intermediate language authors: - Pierre Chambart - video: https://watch.ocaml.org/videos/watch/90d9b62f-f9d6-4dd5-a7fc-f584e45ef0b7 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/90d9b62f-f9d6-4dd5-a7fc-f584e45ef0b7 - title: Statistically profiling memory in OCaml authors: - Jacques-Henri Jourdan @@ -57,15 +57,15 @@ presentations: - Timothy Bourke - Jun Inoue - Marc Pouzet - video: https://watch.ocaml.org/videos/watch/3a00e727-45da-4c4a-a446-927cb28bb6bc + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/3a00e727-45da-4c4a-a446-927cb28bb6bc - title: 'The State of the OCaml Platform: September 2016' authors: - Louis Gesbert, on behalf of the OCaml Platform team - video: https://watch.ocaml.org/videos/watch/c386fc95-092e-4ea7-9317-91edf287fea6 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/c386fc95-092e-4ea7-9317-91edf287fea6 - title: "Who's got your Mail? Mr. Mime" authors: - Romain Calascibetta - video: https://watch.ocaml.org/videos/watch/98a7972d-9323-46b3-81cc-dd86a4cc1ab3 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/98a7972d-9323-46b3-81cc-dd86a4cc1ab3 - title: 'Inuit library: from printf to interactive user-interfaces' authors: - Frédéric Bour diff --git a/data/conferences/2017-ocaml-users-and-developers-workshop.md b/data/conferences/2017-ocaml-users-and-developers-workshop.md index d29eec4976..c15b6806db 100644 --- a/data/conferences/2017-ocaml-users-and-developers-workshop.md +++ b/data/conferences/2017-ocaml-users-and-developers-workshop.md @@ -29,14 +29,14 @@ presentations: authors: - Runhang Li - Jeremy Yallop - video: https://watch.ocaml.org/videos/watch/8d5a83f5-ad98-4f45-9259-c84194134c20 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/8d5a83f5-ad98-4f45-9259-c84194134c20 link: https://github.com/ocaml/ocaml.org-media/blob/master/meetings/ocaml/2017/extended-abstract__2017__runhang-li_jeremy-yallop__extending-ocaml-s-open.pdf additional_links: - https://github.com/objmagic/ocaml-workshop-17-open-ext-talk - title: "Genspio: Generating Shell Phrases In OCaml" authors: - Sebastien Mondet - video: https://watch.ocaml.org/videos/watch/9a7bf8cc-38c5-4f67-ab25-0ea1388100d3 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/9a7bf8cc-38c5-4f67-ab25-0ea1388100d3 link: https://github.com/ocaml/ocaml.org-media/blob/master/meetings/ocaml/2017/extended-abstract__2017__sebastien-mondet__genspio-generating-shell-phrases-in-ocaml.pdf slides: http://wr.mondet.org/slides/OCaml2017-Genspio/ additional_links: @@ -44,7 +44,7 @@ presentations: - title: "Owl: A General-Purpose Numerical Library in OCaml" authors: - Liang Wang - video: https://watch.ocaml.org/videos/watch/d258fa91-ddb6-40d8-96de-e9ac97e8c899 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/d258fa91-ddb6-40d8-96de-e9ac97e8c899 link: https://arxiv.org/abs/1707.09616 slides: https://github.com/ocaml/ocaml.org-media/blob/master/meetings/ocaml/2017/slides__2017__liang_wang__owl-a-general-purpose-numerical-library-in-ocaml.pdf - title: "ROTOR: First Steps Towards a Refactoring Tool for OCaml" @@ -72,7 +72,7 @@ presentations: - title: "The State of the OCaml Platform: September 2017" authors: - Anil Madhavapeddy - video: https://watch.ocaml.org/videos/watch/3940b98a-6b33-41f7-b0e7-4b7ae5ec2b4b + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/3940b98a-6b33-41f7-b0e7-4b7ae5ec2b4b slides: https://speakerdeck.com/avsm/ocaml-platform-2017 link: https://github.com/ocaml/ocaml.org-media/blob/master/meetings/ocaml/2017/slides__2017__anil-madhavapeddy__the-state-of-the-ocaml-platform-september-2017.pdf - title: "Wodan: a pure OCaml, flash-aware filesystem library" diff --git a/data/conferences/2018-ocaml-users-and-developers-workshop.md b/data/conferences/2018-ocaml-users-and-developers-workshop.md index d882a574b0..0fb129fb90 100644 --- a/data/conferences/2018-ocaml-users-and-developers-workshop.md +++ b/data/conferences/2018-ocaml-users-and-developers-workshop.md @@ -28,7 +28,7 @@ presentations: - Jordan Walke - Cheng Lou - Rick Vetter - video: https://watch.ocaml.org/videos/watch/af37368d-085d-431d-923f-cd1d81dfdbe9 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/af37368d-085d-431d-923f-cd1d81dfdbe9 - title: "RFCs, all the way down!" authors: - Romain Calascibetta @@ -36,7 +36,7 @@ presentations: authors: - Charles Chamberlain - Cyrus Omar - video: https://watch.ocaml.org/videos/watch/f75acae0-c24d-4d19-958e-0c76ff51603f + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/f75acae0-c24d-4d19-958e-0c76ff51603f - title: The OCaml Platform 1.0 authors: - Anil Madhavapeddy @@ -54,11 +54,11 @@ presentations: - title: "Wall: rendering vector graphics with OCaml and OpenGL" authors: - Frédéric Bour - video: https://watch.ocaml.org/videos/watch/2472168c-04aa-497d-a931-f866c7036550 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/2472168c-04aa-497d-a931-f866c7036550 - title: "Winning on Windows: porting the OCaml Platform" authors: - David Allsopp - video: https://watch.ocaml.org/videos/watch/5020256d-eeb0-4e0b-81db-cde8ba00e3d7 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/5020256d-eeb0-4e0b-81db-cde8ba00e3d7 program_committee: - name: Andrew Kennedy affiliation: Facebook, London diff --git a/data/conferences/2020-ocaml-users-and-developers-workshop.md b/data/conferences/2020-ocaml-users-and-developers-workshop.md index f70d3965b0..ca6fa31f56 100644 --- a/data/conferences/2020-ocaml-users-and-developers-workshop.md +++ b/data/conferences/2020-ocaml-users-and-developers-workshop.md @@ -14,26 +14,35 @@ important_dates: - date: 2020-08-28 info: OCaml Workshop presentations: + - title: "State of the OCaml Platform 2020" + authors: + - Anil Madhavapeddy + watch_ocamlorg_video: https://watch.ocaml.org/w/2KbfRNv2oLtkKXkbd5u9F1 + youtube_video: https://www.youtube.com/watch?v=E8T_4zqWmq8&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f - title: "A Declarative Syntax Definition for OCaml" authors: - Luis Eduardo de Souza Amorim - Eelco Visser - video: https://watch.ocaml.org/videos/watch/a5b86864-8e43-4138-b6d6-ed48d2d4b63d + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/a5b86864-8e43-4138-b6d6-ed48d2d4b63d + youtube_video: https://www.youtube.com/watch?v=SgP4GlWuUr4&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=11 - title: "A Simple State-Machine Framework for Property-Based Testing in OCaml" authors: - Jan Midtgaard - video: https://watch.ocaml.org/videos/watch/08b429ea-2eb8-427d-a625-5495f4ee0fef + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/08b429ea-2eb8-427d-a625-5495f4ee0fef + youtube_video: https://www.youtube.com/watch?v=uuL9RYuaZV4&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=6 - title: "AD-OCaml: Algorithmic Differentiation for OCaml" authors: - Markus Mottl - video: https://watch.ocaml.org/videos/watch/c9e85690-732f-4b03-836f-2ee0fd8f0658 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/c9e85690-732f-4b03-836f-2ee0fd8f0658 + youtube_video: https://www.youtube.com/watch?v=KUVHbVS-PN4&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=9 - title: "API Migration: compare transformed" authors: - Joseph Harrison - Steven Varoumas - Simon Thompson - Reuben Rowe - video: https://watch.ocaml.org/videos/watch/c46b925b-bd77-404f-ac5d-5dab65047529 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/c46b925b-bd77-404f-ac5d-5dab65047529 + youtube_video: https://www.youtube.com/watch?v=y6RKnOu4i74&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=4 - title: "Irmin v2" authors: - Clément Pascutto @@ -41,16 +50,19 @@ presentations: - Craig Ferguson - Thomas Gazagnaire - Romain Liautaud - video: https://watch.ocaml.org/videos/watch/53e497b0-898f-4c85-8da9-39f65ef0e0b1 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/53e497b0-898f-4c85-8da9-39f65ef0e0b1 + youtube_video: https://www.youtube.com/watch?v=v1lfMUM332w&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=8 - title: "LexiFi Runtime Types" authors: - Patrik Keller - Marc Lasson - video: https://watch.ocaml.org/videos/watch/cc7e3242-0bef-448a-aa13-8827bba933e3 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/cc7e3242-0bef-448a-aa13-8827bba933e3 + youtube_video: https://www.youtube.com/watch?v=0BpmxJGaaFo&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=12 - title: "OCaml Under The Hood: SmartPy" authors: - Sebastien Mondet - video: https://watch.ocaml.org/videos/watch/7446ad4d-4ae2-4e1a-bc38-af8f71e8ebd8 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/7446ad4d-4ae2-4e1a-bc38-af8f71e8ebd8 + youtube_video: https://www.youtube.com/watch?v=z8YN2oT2gGY&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=10 - title: "OCaml-CI: A Zero-Configuration CI" authors: - Thomas Leonard @@ -58,7 +70,8 @@ presentations: - Kate Deplaix - Magnus Skjegstad - Anil Madhavapeddy - video: https://watch.ocaml.org/videos/watch/da88d6ac-7ba1-4261-9308-d03fe21e35b9 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/da88d6ac-7ba1-4261-9308-d03fe21e35b9 + youtube_video: https://www.youtube.com/watch?v=HjcCUZ9i-ug&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=2 - title: "Parallelising your OCaml Code with Multicore OCaml" authors: - Sadiq Jaffer @@ -66,23 +79,27 @@ presentations: - KC Sivaramakrishnan - Tom Kelly - Anil Madhavapeddy - video: https://watch.ocaml.org/videos/watch/ce20839e-4bfc-4d74-925b-485a6b052ddf + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/ce20839e-4bfc-4d74-925b-485a6b052ddf + youtube_video: https://www.youtube.com/watch?v=Z7YZR1q8wzI&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=5 link: https://github.com/ocaml-multicore/multicore-talks/tree/master/ocaml2020-workshop-parallel - title: "The ImpFS filesystem" authors: - Tom Ridge - video: https://watch.ocaml.org/videos/watch/28545b27-4637-47a5-8edd-6b904daef19c + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/28545b27-4637-47a5-8edd-6b904daef19c + youtube_video: https://www.youtube.com/watch?v=wwzbSeiXbno&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=7 - title: "The Final Pieces of the OCaml Documentation Puzzle" authors: - Jonathan Ludlam - Gabriel Radanne - Leo White - video: https://watch.ocaml.org/videos/watch/2acebff9-25fa-4733-83cc-620a65b12251 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/2acebff9-25fa-4733-83cc-620a65b12251 + youtube_video: https://www.youtube.com/watch?v=wVyZ-KveN-w&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=3 - title: "Types in amber" authors: - Paul Steckler - Matthew Ryan - video: https://watch.ocaml.org/videos/watch/99b3dc75-9f93-4677-9f8b-076546725512 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/99b3dc75-9f93-4677-9f8b-076546725512 + youtube_video: https://www.youtube.com/watch?v=jroMKd7MzT4&list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f&index=13 program_committee: - name: Ivan Gotovchits affiliation: CMU, USA diff --git a/data/conferences/2021-ocaml-users-and-developers-workshop.md b/data/conferences/2021-ocaml-users-and-developers-workshop.md index 84d0eea6d4..f140b1e259 100644 --- a/data/conferences/2021-ocaml-users-and-developers-workshop.md +++ b/data/conferences/2021-ocaml-users-and-developers-workshop.md @@ -13,13 +13,15 @@ presentations: - title: "25 Years of OCaml" authors: - Xavier Leroy - video: https://watch.ocaml.org/videos/watch/e1ee0fc0-50ef-4a1c-894a-17df181424cb + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/e1ee0fc0-50ef-4a1c-894a-17df181424cb + youtube_video: https://www.youtube.com/watch?v=PGJdHUqgX7o&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=11 - title: "A Multiverse of Glorious Documentation" authors: - Lucas Pluvinage - Jonathan Ludlam - video: https://watch.ocaml.org/videos/watch/9bb452d6-1829-4dac-a6a2-46b31050c931 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/9bb452d6-1829-4dac-a6a2-46b31050c931 link: https://icfp21.sigplan.org/details/ocaml-2021-papers/15/A-Multiverse-of-Glorious-Documentation + youtube_video: https://www.youtube.com/watch?v=qUMbbKwagaU&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=9 - title: "Adapting the OCaml Ecosystem for Multicore OCaml" authors: - Sudha Parimala @@ -28,32 +30,36 @@ presentations: - Tom Kelly - KC Sivaramakrishnan link: https://icfp21.sigplan.org/details/ocaml-2021-papers/7/Adapting-the-OCaml-ecosystem-for-Multicore-OCaml - video: https://watch.ocaml.org/videos/watch/629b89a8-bbd5-490d-98b0-d0c740912b02 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/629b89a8-bbd5-490d-98b0-d0c740912b02 + youtube_video: https://www.youtube.com/watch?v=MfjMpznU4nM&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=3 - title: "Binary Analysis Platform (BAP). Using Universal Algebra and Tagless-Final Style for Developing Representation-Agnostic Frameworks" authors: - Ivan Gotovchits - David Brumley - video: https://watch.ocaml.org/videos/watch/8dc2d8d3-c140-4c3d-a8fe-a6fcf6fba988 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/8dc2d8d3-c140-4c3d-a8fe-a6fcf6fba988 + youtube_video: https://www.youtube.com/watch?v=S9XPI1fHWqM&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=18 link: https://icfp21.sigplan.org/details/ocaml-2021-papers/10/Binary-Analysis-Platform-BAP-Using-Universal-Algebra-and-Tagless-Final-Style-for-D - title: "Continuous Benchmarking for OCaml Projects" authors: - Gargi Sharma - Rizo Isrof - Magnus Skjegstad - video: https://watch.ocaml.org/videos/watch/1c994370-1aaa-4db6-b901-d762786e4904 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/1c994370-1aaa-4db6-b901-d762786e4904 + youtube_video: https://www.youtube.com/watch?v=folKaWN7jy4&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=8 - title: "Deductive Verification of Realistic OCaml Code" authors: - Carlos Pinto - Mário Pereira - Simão Melo de Sousa - video: https://watch.ocaml.org/videos/watch/92309d92-8cbf-4545-980c-209c96e42a79 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/92309d92-8cbf-4545-980c-209c96e42a79 - title: "Digodoc and Docs" authors: - Mohamed Hernouf - Fabrice Le Fessant - Thomas Blanc - Louis Gesbert - video: https://watch.ocaml.org/videos/watch/db6ed2c4-e940-4d5f-82ee-d3d20eb4ceb7 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/db6ed2c4-e940-4d5f-82ee-d3d20eb4ceb7 + youtube_video: https://www.youtube.com/watch?v=gODavKhyd2I&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=10 - title: "Experiences with Effects" authors: - Thomas Leonard @@ -64,37 +70,44 @@ presentations: - KC Sivaramakrishnan - Anil Madhavapeddy link: https://icfp21.sigplan.org/details/ocaml-2021-papers/16/Experiences-with-Effects - video: https://watch.ocaml.org/videos/watch/74ece0a8-380f-4e2a-bef5-c6bb9092be89 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/74ece0a8-380f-4e2a-bef5-c6bb9092be89 + youtube_video: https://www.youtube.com/watch?v=k3oQwpyXmpo&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=12 - title: "From 2n+1 to n" authors: - Nandor Licker - Timothy M. Jones - video: https://watch.ocaml.org/videos/watch/74b32dae-11c6-4713-be1b-946260196e50 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/74b32dae-11c6-4713-be1b-946260196e50 + youtube_video: https://www.youtube.com/watch?v=3xRGeJSslPE&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=15 link: https://icfp21.sigplan.org/details/ocaml-2021-papers/14/From-2n-1-to-n - title: "GopCaml: A Structural Editor for OCaml" authors: - Kiran Gopinathan link: https://icfp21.sigplan.org/details/ocaml-2021-papers/11/GopCaml-A-Structural-Editor-for-OCaml - video: https://watch.ocaml.org/videos/watch/e0a6e6f2-0d40-4dfc-9308-001c8e0f64d6 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/e0a6e6f2-0d40-4dfc-9308-001c8e0f64d6 + youtube_video: https://www.youtube.com/watch?v=KipRuiLXYEo&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo - title: "Leveraging Formal Specifications to Generate Fuzzing Suites" authors: - Nicolas Osborne - Clément Pascutto - video: https://watch.ocaml.org/videos/watch/d9a36c9f-1611-42f9-8854-981b1e2d7d75 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/d9a36c9f-1611-42f9-8854-981b1e2d7d75 + youtube_video: https://www.youtube.com/watch?v=-6fpLF_n7cA&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=6 - title: "Love: a readable language interpreted by a blockchain" authors: - Steven de Oliveira - David Declerck - video: https://watch.ocaml.org/videos/watch/d3b2b31e-1739-406e-8de7-d5f21bc01836 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/d3b2b31e-1739-406e-8de7-d5f21bc01836 + youtube_video: https://www.youtube.com/watch?v=um55QNwz8o4&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=14 - title: "OCaml and Python: Getting the Best of Both Worlds" authors: - Laurent Mazare - video: https://watch.ocaml.org/videos/watch/9eafdb1e-9be9-4a52-98b4-f4696eda4c18 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/9eafdb1e-9be9-4a52-98b4-f4696eda4c18 + youtube_video: https://www.youtube.com/watch?v=ZseAgG9kmMw&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=2 - title: "Opam-bin: Binary Packages with Opam" authors: - Fabrice Le Fessant link: https://icfp21.sigplan.org/details/ocaml-2021-papers/5/Opam-bin-Binary-Packages-with-Opam - video: https://watch.ocaml.org/videos/watch/a889e4d3-0508-4734-b667-7060b0a253cd + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/a889e4d3-0508-4734-b667-7060b0a253cd + youtube_video: https://www.youtube.com/watch?v=vadoOkgEs6w&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=13 - title: "Parafuzz: Coverage-guided Property Fuzzing for Multicore OCaml programs" authors: - Sumit Padhiyar @@ -102,30 +115,36 @@ presentations: - KC Sivaramakrishnan link: https://icfp21.sigplan.org/details/ocaml-2021-papers/9/Parafuzz-Coverage-guided-Property-Fuzzing-for-Multicore-OCaml-programs slides: https://speakerdeck.com/kayceesrk/parafuzz-fuzzing-multicore-ocaml-programs - video: https://watch.ocaml.org/videos/watch/c0d591e0-91c9-4eaa-a4d7-c4f514de0a57 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/c0d591e0-91c9-4eaa-a4d7-c4f514de0a57 + youtube_video: https://www.youtube.com/watch?v=GZsUoSaIpIs&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=4 - title: "Probabilistic resource limits, or: Programming with interrupts in OCaml" authors: - Guillaume Munch-Maccagnoni - video: https://watch.ocaml.org/videos/watch/bc297e85-82dd-4baf-8556-4a3a934978f9 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/bc297e85-82dd-4baf-8556-4a3a934978f9 + youtube_video: https://www.youtube.com/watch?v=9OES0qe_OvE&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=7 - title: "Property-Based Testing for OCaml through Coq" authors: - Paaras Bhandari - Leonidas Lampropoulos - video: https://watch.ocaml.org/videos/watch/9324fba4-2482-4bab-bfdd-b8881b3ed94a + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/9324fba4-2482-4bab-bfdd-b8881b3ed94a + youtube_video: https://www.youtube.com/watch?v=w-dTTlVwVgY&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=16 - title: "Safe Protocol Updates via Propositional Logic" authors: - Michael O'Connor - video: https://watch.ocaml.org/videos/watch/c6176f51-0277-46f0-937b-1e2721044492 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/c6176f51-0277-46f0-937b-1e2721044492 + youtube_video: https://www.youtube.com/watch?v=ckN1YREM3Gk&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=17 - title: "Semgrep, a fast, lightweight, polyglot, static analysis tool to find bugs" authors: - Yoann Padioleau link: https://icfp21.sigplan.org/details/ocaml-2021-papers/18/Semgrep-a-fast-lightweight-polyglot-static-analysis-tool-to-find-bugs - video: https://watch.ocaml.org/videos/watch/c0d07213-1426-46a1-98e0-0b0c4515c841 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/c0d07213-1426-46a1-98e0-0b0c4515c841 + youtube_video: https://www.youtube.com/watch?v=q7kuvyAOk78&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=19 - title: "Wibbily Wobbly Timey Camly" authors: - Di Long Li - Gabriel Radanne - video: https://watch.ocaml.org/videos/watch/ec641446-823b-40ec-a207-85157a18f88e + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/ec641446-823b-40ec-a207-85157a18f88e + youtube_video: https://www.youtube.com/watch?v=3Jpla-vWLR4&list=PLKO_ZowsIOu7o3iQmS3InxLKd0L5-zyqo&index=5 organising_committee: - name: Frédéric Bour affiliation: Tarides, France diff --git a/data/conferences/2022-ocaml-users-and-developers-workshop.md b/data/conferences/2022-ocaml-users-and-developers-workshop.md index 4ba69b9f62..0907862c9c 100644 --- a/data/conferences/2022-ocaml-users-and-developers-workshop.md +++ b/data/conferences/2022-ocaml-users-and-developers-workshop.md @@ -15,22 +15,25 @@ presentations: - Deepali Ande - KC Sivaramakrishnan link: https://kcsrk.info/papers/compose_ocaml22.pdf - video: https://watch.ocaml.org/videos/watch/08ea09a1-e645-47cb-80c4-499dd4d93ac8 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/08ea09a1-e645-47cb-80c4-499dd4d93ac8 + youtube_video: https://www.youtube.com/watch?v=PrZqByjFyHI&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2&index=4 - title: "Continuous Monitoring of OCaml Applications Using Runtime Events" authors: - Sadiq Jaffer - Patrick Ferris link: https://github.com/patricoferris/runtime-events-demo/blob/main/abstract.pdf - video: https://watch.ocaml.org/videos/watch/299cab02-db94-44ac-b926-ea90ddda1b09 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/299cab02-db94-44ac-b926-ea90ddda1b09 - title: "Copying opam Switches - It Should Just Work™" authors: - David Allsopp - video: https://watch.ocaml.org/videos/watch/8c1c3fda-0106-4c7d-a794-33da7e758fee + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/8c1c3fda-0106-4c7d-a794-33da7e758fee + youtube_video: https://www.youtube.com/watch?v=5JDSUCx-tPw&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2&index=7 - title: "Efficient “Out of Heap” Pointers for Multicore OCaml" authors: - Guillaume Munch-Maccagnoni link: https://guillaume.munch.name/files/large-pages-ocamlworkshop.pdf - video: https://watch.ocaml.org/videos/watch/0aa64600-b142-4c11-964d-dab8d509d08f + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/0aa64600-b142-4c11-964d-dab8d509d08f + youtube_video: https://www.youtube.com/watch?v=eIQf1bRl8_k&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2&index=5 - title: "Highest-Performance Stream Processing" authors: - Oleg Kiselyov @@ -38,7 +41,8 @@ presentations: - Aggelos Biboudis - Nick Palladinos link: https://okmij.org/ftp/meta-programming/strymonasv2-intro.pdf - video: https://watch.ocaml.org/videos/watch/c75ed758-d513-4453-af68-c50c1d9a1469 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/c75ed758-d513-4453-af68-c50c1d9a1469 + youtube_video: https://www.youtube.com/watch?v=w47xZKfQbWI&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2&index=3 - title: "Homogeneous Builds with OBuilder and OCaml" authors: - Tim McGilchrist @@ -49,7 +53,8 @@ presentations: - Anil Madhavapeddy - Kate Deplaix link: https://github.com/tmcgilchrist/ocaml-2022-submission/blob/master/ocurrent.pdf - video: https://watch.ocaml.org/videos/watch/29055525-2b0f-4f00-a0a0-26c9d4e97f9c + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/29055525-2b0f-4f00-a0a0-26c9d4e97f9c + youtube_video: https://www.youtube.com/watch?v=XopV5Gd6hPo&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2&index=11 - title: "Introducing the Bindoj Library, a Datatype-Centric Generative Programming Library for Real-World Programming in OCaml" authors: - Haochen M. Kotoi-Xie @@ -57,19 +62,22 @@ presentations: - Yuta Sato - Shinya Yamaguchi link: https://icfp22.sigplan.org/details/ocaml-2022-papers/14/Introducing-the-Bindoj-library-a-datatype-centric-generative-programming-library-for - video: https://watch.ocaml.org/videos/watch/69755b27-85b1-4df4-9f01-b771cd15353a + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/69755b27-85b1-4df4-9f01-b771cd15353a + youtube_video: https://www.youtube.com/watch?v=2TM-8lYQctM&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2&index=12 - title: "Memo: An Incremental Computation Library That Powers Dune" authors: - Andrey Mokhov - Arseniy Alekseyev link: https://icfp22.sigplan.org/details/ocaml-2022-papers/4/Memo-an-incremental-computation-library-that-powers-Dune - video: https://watch.ocaml.org/videos/watch/d6a126b9-05f6-4b0f-ac6b-ad14d9bf12c9 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/d6a126b9-05f6-4b0f-ac6b-ad14d9bf12c9 + youtube_video: https://www.youtube.com/watch?v=MjWx_qfEQXg&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2&index=2 - title: "Multicoretests - Parallel Testing Libraries for OCaml 5.0" authors: - Jan Midtgaard - Olivier Nicole - Nicolas Osborne - video: https://watch.ocaml.org/videos/watch/c844f844-acc1-4a8a-944e-4d99343a89c5 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/c844f844-acc1-4a8a-944e-4d99343a89c5 + youtube_video: https://www.youtube.com/watch?v=vxb6W6DqMGk&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2&index=8 - title: "OCamello: A Course and Summer School with Learn-OCaml" authors: - Roberto Blanco @@ -84,27 +92,31 @@ presentations: - Stephen Dolan - Leo White link: http://stedolan.net/talks/ocaml22 - video: https://watch.ocaml.org/videos/watch/6c86b050-334b-4a11-bb04-c347a6e57215 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/6c86b050-334b-4a11-bb04-c347a6e57215 + youtube_video: https://www.youtube.com/watch?v=yGRn5ZIbEW8&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2 - title: "Supporting a Decade of Opam" authors: - David Allsopp - Raja Boujbel - Kate Deplaix - Louis Gesbert - video: https://watch.ocaml.org/videos/watch/039f1096-a63c-4a88-af4b-dcc48791d723 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/039f1096-a63c-4a88-af4b-dcc48791d723 + youtube_video: https://www.youtube.com/watch?v=7_q0QfDTD5M&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2&index=9 - title: "Supporting FLAT Concepts in Learn-OCaml: Seeing is Believing; Programming is Understanding" authors: - Artur Miguel Dias - Simão Melo de Sousa - Antonio Ravara link: https://release.di.ubi.pt/leafs/publications/ocamlws22.pdf - video: https://watch.ocaml.org/videos/watch/aa552395-666e-4394-a42f-faaa6f3da92c + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/aa552395-666e-4394-a42f-faaa6f3da92c + youtube_video: https://www.youtube.com/watch?v=kUB1ujU4tkc&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2&index=10 - title: "Tracing OCaml Programs" authors: - Darius Foo - Wei-Ngan Chin link: https://web.archive.org/web/20230413145607/https://dariusf.github.io/tracing-ocaml22.pdf - video: https://watch.ocaml.org/videos/watch/3b4401ec-f0a8-44bb-97ad-18e05c2135f9 + watch_ocamlorg_video: https://watch.ocaml.org/videos/watch/3b4401ec-f0a8-44bb-97ad-18e05c2135f9 + youtube_video: https://www.youtube.com/watch?v=MwVeZrDyewU&list=PLKO_ZowsIOu7E935Gdr6vRB44NT6gOjW2&index=6 organising_committee: [] program_committee: - name: Matija Pretnar @@ -140,5 +152,5 @@ ACM Sigplan ICFP page: [OCaml Workskop 2022](https://icfp22.sigplan.org/home/oca The OCaml Users and Developers Workshop brings together the OCaml community, including users of OCaml in industry, academia, hobbyists, and the free software community. -Video recordings will be available on the [Sigplan YouTube Channel](https://www.youtube.com/channel/UCwG9512Wm7jSS6Iqshz4Dpg) and on [Watch OCaml](https://watch.ocaml.org/video-channels/ocaml2022/videos). +Video recordings can be found on the [@OCamlWorkshops YouTube Channel](https://www.youtube.com/@OCamlWorkshops) and on [Watch OCaml](https://watch.ocaml.org/video-channels/ocaml2022/videos). diff --git a/data/conferences/2023-ocaml-users-and-developers-workshop.md b/data/conferences/2023-ocaml-users-and-developers-workshop.md index 0aa6b24805..d7c798a423 100644 --- a/data/conferences/2023-ocaml-users-and-developers-workshop.md +++ b/data/conferences/2023-ocaml-users-and-developers-workshop.md @@ -15,6 +15,7 @@ presentations: - Shayne Fletcher - Neil Mitchell link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/1/Buck2-for-OCaml-Users-Developers" + youtube_video: https://www.youtube.com/watch?v=l4X4BxEEe-w&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=6 - title: "Building a Lock-Free STM for OCaml" authors: - Vesa Karvonen @@ -25,12 +26,14 @@ presentations: - YSS Narasimha Naidu - Sudha Parimala link: "https://polytypic.github.io/kcas-talk/#/5" + youtube_video: https://www.youtube.com/watch?v=Mt8wPCHU1ZU&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=12 - title: "Efficient OCaml Compilation With Flambda 2" authors: - Pierre Chambart - Vincent LAVIRON - Mark Shinwell link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/8/Efficient-OCaml-compilation-with-Flambda-2" + youtube_video: https://www.youtube.com/watch?v=eI5GBpT2Brs&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=5 - title: "Eio 1.0 – Effects-Based I/O for OCaml 5" authors: - Thomas Leonard @@ -43,32 +46,38 @@ presentations: - Vincent Balat - Anil Madhavapeddy link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/5/Eio-1-0-Effects-based-IO-for-OCaml-5" - - title: "Flambda 2 Types: An Abstract Domain for Static Analysis of Functional Programs" + youtube_video: https://www.youtube.com/watch?v=jr4LsCVQBj4&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=2 + - title: "[ML'23] Flambda 2 Types: An Abstract Domain for Static Analysis of Functional Programs" authors: - Vincent LAVIRON - Pierre Chambart - Mark Shinwell link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/9/Flambda-2-Types-An-abstract-domain-for-static-analysis-of-functional-programs" + youtube_video: https://www.youtube.com/watch?v=PRb8tRfxX3s&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=16 - title: "Less Power for More Learning: Restricting OCaml Features for Effective Teaching" authors: - Max Lang - Nico Petzendorfer link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/11/Less-Power-for-More-Learning-Restricting-OCaml-Features-for-Effective-Teaching" + youtube_video: https://www.youtube.com/watch?v=Olt2mj_K2rk&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=7 - title: "MetaOCaml Theory and Implementation" authors: - Oleg Kiselyov link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/3/MetaOCaml-Theory-and-Implementation" + youtube_video: https://www.youtube.com/watch?v=1fn1AEHeu2I&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=3 - title: "Modern DSL Compiler Architecture in OCaml Our Experience With Catala" authors: - Louis Gesbert - Denis Merigoux link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/4/Modern-DSL-compiler-architecture-in-OCaml-our-experience-with-Catala" + youtube_video: https://www.youtube.com/watch?v=pO8Z4lcY0ys&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=4 - title: "Osiris: An Iris-Based Program Logic for OCaml" authors: - Arnaud Daby-Seesaram - François Pottier - Armaël Guéneau link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/7/Osiris-an-Iris-based-program-logic-for-OCaml" + youtube_video: https://www.youtube.com/watch?v=osYEG4WHMyA&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=10 - title: "Owi: An Interpreter and a Toolkit for WebAssembly Written in OCaml" authors: - Léo Andrès @@ -76,22 +85,26 @@ presentations: - Eric Patrizio - Dario Pinto link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/14/Owi-an-interpreter-and-a-toolkit-for-WebAssembly-written-in-OCaml" + youtube_video: https://www.youtube.com/watch?v=IM76cMP3Eqo&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=11 - title: "Parallel Sequences in Multicore OCaml" authors: - Andrew Tao link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/2/Parallel-Sequences-in-Multicore-OCaml" + youtube_video: https://www.youtube.com/watch?v=cMsYwkMOB9M&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=8 - title: "Runtime Detection of Data Races in OCaml with ThreadSanitizer" authors: - Olivier Nicole - Fabrice Buoro link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/12/Runtime-Detection-of-Data-Races-in-OCaml-with-ThreadSanitizer" - - title: "Safe and Efficient Generic Functions With MacoCaml" + youtube_video: https://www.youtube.com/watch?v=zr9S0Fr_Chc&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=9 + - title: "[ICFP'23] MacoCaml: Staging Composable and Compilable Macros" authors: - Dmitrij Szamozvancev - Leo White - Ningning Xie - Jeremy Yallop link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/16/Safe-and-efficient-generic-functions-with-MacoCaml" + youtube_video: https://www.youtube.com/watch?v=xnCasjtSEYo&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=12 - title: "State of the OCaml Platform 2023" authors: - Thibaut Mattio @@ -99,15 +112,18 @@ presentations: - Thomas Gazagnaire - David Allsopp link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/15/State-of-the-OCaml-Platform-2023" + youtube_video: https://www.youtube.com/watch?v=i4ZQ2EGI8sY&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=1 - title: "Targeted Static Analysis for OCaml C Stubs: Eliminating gremlins from the code" authors: - Edwin Török link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/10/Targeted-Static-Analysis-for-OCaml-C-Stubs-Eliminating-gremlins-from-the-code" - - title: "Wasocaml: A Compiler From OCaml to WebAssembly" + youtube_video: https://www.youtube.com/watch?v=Of3dxdY3Z9M&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=13 + - title: "[ML'23] Wasocaml: A Compiler From OCaml to WebAssembly" authors: - Léo Andrès - Pierre Chambart link: "https://icfp23.sigplan.org/details/ocaml-2023-papers/13/Wasocaml-a-compiler-from-OCaml-to-WebAssembly" + youtube_video: https://www.youtube.com/watch?v=i8PQXQ6a22Q&list=PLKO_ZowsIOu7JRDyxO99qz1jBpPvUnuEf&index=14 organising_committee: [] program_committee: - name: Kenichi Asai @@ -149,3 +165,6 @@ OCaml Workshop 2023 took place during ICFP 2023, in Seattle, Washington, United ACM Sigplan ICFP page: [OCaml Workskop 2023](https://icfp23.sigplan.org/home/ocaml-2023) The OCaml Users and Developers Workshop brings together the OCaml community, including users of OCaml in industry, academia, hobbyists, and the free software community. + +Video recordings can be found on the [@OCamlWorkshops YouTube Channel](https://www.youtube.com/@OCamlWorkshops). + diff --git a/data/conferences/2024-fun-ocaml.md b/data/conferences/2024-fun-ocaml.md new file mode 100644 index 0000000000..ab48b3e8c7 --- /dev/null +++ b/data/conferences/2024-fun-ocaml.md @@ -0,0 +1,96 @@ +--- +title: FUN OCaml 2024 +date: 2024-09-16 +location: Berlin, Germany +important_dates: + - date: 2024-09-16 + info: FUN OCaml +presentations: + - title: "Maybe OCaml Was the Friends We Made Along the Way" + authors: + - Dillon Mulroy + youtube_video: https://www.youtube.com/watch?v=1HlIHPa38gY + watch_ocamlorg_video: https://watch.ocaml.org/w/rwDYUk9N3X9cMRyhCav35X + - title: "Easy GADTs by Repeating Yourself" + authors: + - Eduardo Rafael + youtube_video: https://www.youtube.com/watch?v=-XYO_ILJG2M + watch_ocamlorg_video: https://watch.ocaml.org/w/3i71o7rfq7UzzpTRyCSx2w + - title: "The Story Behind the Fastest Image Comparison Library" + authors: + - Dmitriy Kovalenko + youtube_video: https://www.youtube.com/watch?v=hTAvAKolWd8 + watch_ocamlorg_video: https://watch.ocaml.org/w/hSHDx6iT8z9PBgoaXNnFmW + - title: "Universal React in OCaml" + authors: + - David Sancho Moreno + youtube_video: https://www.youtube.com/watch?v=Oy3lZl2kE-0 + watch_ocamlorg_video: https://watch.ocaml.org/w/wwYKmvEH8CqKZ7TzRAEZXq + - title: "The Future of Dune" + authors: + - Leandro Ostera + youtube_video: https://www.youtube.com/watch?v=7_bv3EvQANY + watch_ocamlorg_video: https://watch.ocaml.org/w/2A6bTKjqQ1StL6yfQehnvp + - title: "MirageOS - Developing Operating Systems in OCaml" + authors: + - Hannes Mehnert + youtube_video: https://www.youtube.com/watch?v=g7Kl5mRDCDo + watch_ocamlorg_video: https://watch.ocaml.org/w/8guYKggC1zYWk8MjcHLtG9 + - title: "Learning OCaml with Tiny Code Xmas" + authors: + - Michael Dales + youtube_video: https://www.youtube.com/watch?v=2ZswyN4aP2o + watch_ocamlorg_video: https://watch.ocaml.org/w/bBWrw9qh6AaEFVRmFCFMKT + - title: "Let Signals in OCaml" + authors: + - Rizo Isrof + youtube_video: https://www.youtube.com/watch?v=34bceAuSRXE + watch_ocamlorg_video: https://watch.ocaml.org/w/78sg2vm4WzbKvcbSmtCpwd + - title: "A 'Melange' of Tooling Coming Together" + authors: + - Antonio Monteiro + youtube_video: https://www.youtube.com/watch?v=3oCXT-ycHHs + watch_ocamlorg_video: https://watch.ocaml.org/w/vCzFWXa4RfN6y7BTSenBY5 + - title: "How the Multicore Garbage Collector works" + authors: + - Sudha Parimala + youtube_video: https://www.youtube.com/watch?v=fgdB_9DcJj4 + watch_ocamlorg_video: https://watch.ocaml.org/w/772GsUvu7eRobHgLDUeE2M + - title: "Building Incremental and Reproducible Data Pipelines" + authors: + - Patrick Ferris + youtube_video: https://www.youtube.com/watch?v=6mxx2j1jmhE + watch_ocamlorg_video: https://watch.ocaml.org/w/21fL5BUJxWdLigoALGMpLb + - title: "Type engineering in OCaml, Illustrated on the OCaml Compiler" + authors: + - Florian Angeletti + youtube_video: https://www.youtube.com/watch?v=FHWH6ayUV8c + watch_ocamlorg_video: https://watch.ocaml.org/w/g8xFJmbxhyXDnpwaT6pBJm + - title: "Using odoc to Write Documentation" + authors: + - Paul-Elliot Anglès d'Auriac + youtube_video: https://www.youtube.com/watch?v=Qzf_ZB1TKLQ + watch_ocamlorg_video: https://watch.ocaml.org/w/uFvC5GQU8jChh5PmGNrmTo + - title: "OCANNL, the `neural_nets_lib`" + authors: + - Lukasz Stafiniak + youtube_video: https://www.youtube.com/watch?v=1J2XyHLb2J0 + watch_ocamlorg_video: https://watch.ocaml.org/w/vQYhM1uQ3d3ZACKfRPCtrq +organising_committee: + - name: Sabine Schmaltz + affiliation: Tarides + - name: David Sancho + affiliation: Ahrefs + - name: Dmitriy Kovalenko +program_committee: [] +--- + +FUN OCaml 2024 took place in Berlin, Germany + +FUN OCaml homepage: [FUN OCaml](https://fun-ocaml.com) + + +Video recordings are available here: +* [FUN OCaml 2024 YouTube Playlist](https://youtube.com/playlist?list=PLP3MfTGqcNVJMFcWWDF6VSPJB7zuKN5yQ&si=M4OouS2iS_sOrpzR) +* [FUN OCaml 2024 Watch OCaml Playlist](https://watch.ocaml.org/w/p/6AFNv2zJg3BcswcFdPMNvP) + diff --git a/data/conferences/2024-ocaml-users-and-developers-workshop.md b/data/conferences/2024-ocaml-users-and-developers-workshop.md new file mode 100644 index 0000000000..c21f796ec5 --- /dev/null +++ b/data/conferences/2024-ocaml-users-and-developers-workshop.md @@ -0,0 +1,148 @@ +--- +title: OCaml Workshop 2024 +date: 2024-09-07 +location: Milan, Italy +important_dates: + - date: 2024-05-30 + info: Abstract submission deadline + - date: 2024-07-04 + info: Author notification + - date: 2024-09-07 + info: OCaml Workshop +presentations: + - title: "A Non-allocating Option" + authors: + - Richard A. Eisenberg + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/8/A-Non-allocating-Option" + youtube_video: https://www.youtube.com/watch?v=9R9RFvjXMCU&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=6 + - title: "B · o · B, a universal & secure file-transfer software in OCaml" + authors: + - Romain Calascibetta + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/2/B-o-B-a-universal-secure-file-transfer-software-in-OCaml" + youtube_video: https://www.youtube.com/watch?v=COmi9e7wHtI&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=3 + - title: "ChorCaml: Functional Choreographic Programming in OCaml" + authors: + - Rokas Urbonas + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/13/ChorCaml-Functional-Choreographic-Programming-in-OCaml" + youtube_video: https://www.youtube.com/watch?v=KEkmcXVtFi0&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=9 + - title: "Distributed Actors in OCaml" + authors: + - Wenke DU + - Gabriel Radanne + - Ludovic Henrio + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/9/Distributed-Actors-in-OCaml" + youtube_video: https://www.youtube.com/watch?v=FbsYIA38eng&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=4 + - title: "First-Class Windows: Building a Roadmap for OCaml on Windows" + authors: + - Sudha Parimala + - Benjamin Canou + - Pierre Boutillier + - David Allsopp + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/14/First-Class-Windows-Building-a-Roadmap-for-OCaml-on-Windows" + youtube_video: https://www.youtube.com/watch?v=wjb63CS7fdE&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=10 + - title: "Flambda2 Validator" + authors: + - Irene Yoon + - Chris Casinghino + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/6/Flambda2-Validator" + youtube_video: https://www.youtube.com/watch?v=phon73Ku-nM&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=15 + - title: "Mica: Automated Differential Testing for OCaml Modules" + authors: + - Ernest Ng + - Harrison Goldstein + - Benjamin C. Pierce + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/4/Mica-Automated-Differential-Testing-for-OCaml-Modules" + youtube_video: https://www.youtube.com/watch?v=dQFjZI19Jd8&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=11 + - title: "Mixed Blocks: Storing More Fields Flat" + authors: + - Nicholas Roberts + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/7/Mixed-Blocks-Storing-More-Fields-Flat" + youtube_video: https://www.youtube.com/watch?v=cnNe83QbZHU&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=16 + - title: "On the design and implementation of Modular Explicits" + authors: + - Samuel Vivien + - Didier Rémy + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/1/On-the-design-and-implementation-of-Modular-Explicits" + youtube_video: https://www.youtube.com/watch?v=5AccIR_TP1A&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=1 + - title: "Opam 2.2 and beyond" + authors: + - Raja Boujbel + - Kate Deplaix + - David Allsopp + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/10/Opam-2-2-and-beyond" + youtube_video: https://www.youtube.com/watch?v=vpASgFrwKEE&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=12 + - title: "Picos — Interoperable effects based concurrency" + authors: + - Vesa Karvonen + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/5/Picos-Interoperable-effects-based-concurrency" + youtube_video: https://www.youtube.com/watch?v=iVpsVqd6eNE&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=7 + - title: "Priodomainslib: Prioritized Fine-grained Parallelism for Multicore OCaml" + authors: + - Stefan K. Muller + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/15/Priodomainslib-Prioritized-Fine-grained-Parallelism-for-Multicore-OCaml" + youtube_video: https://www.youtube.com/watch?v=7yYC6EGYg10&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=8 + - title: "Project-wide occurrences for OCaml, a progress report" + authors: + - Ulysse Gérard + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/3/Project-wide-occurrences-for-OCaml-a-progress-report" + youtube_video: https://www.youtube.com/watch?v=QxW1tDB88aY&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=13 + - title: "Recursion schemes in OCaml: An experience report" + authors: + - Tim Williams + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/11/Recursion-schemes-in-OCaml-An-experience-report" + youtube_video: https://www.youtube.com/watch?v=AWH3DTDyAII&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=2 + - title: "Saturn: a library of verified concurrent data structures for OCaml 5" + authors: + - Clément Allain + - Vesa Karvonen + - Carine Morel + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/12/Saturn-a-library-of-verified-concurrent-data-structures-for-OCaml-5" + youtube_video: https://www.youtube.com/watch?v=vanyv3ZEto8&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=5 + - title: "Structured diagnostics for the OCaml compiler" + authors: + - Florian Angeletti + link: "https://icfp24.sigplan.org/details/ocaml-2024-papers/16/Structured-diagnostics-for-the-OCaml-compiler" + youtube_video: https://www.youtube.com/watch?v=tjPgg7hXodE&list=PLKO_ZowsIOu52jtALkYCvu_PnUTq0iBP_&index=14 +organising_committee: [] +program_committee: + - name: Armaël Guéneau + affiliation: Inria Saclay - LMF + role: co-chair + - name: Sonja Heinze + affiliation: Tarides + role: co-chair + - name: Abigael Decorne + - name: Antonio Monteiro + - name: Carine Morel + affiliation: Tarides + - name: Enrico Tassi + affiliation: INRIA + - name: Hugo Heuzard + - name: Kate Deplaix + affiliation: Consultant for the OCaml Software Foundation and Ahrefs + - name: Marcello Seri + affiliation: Bernoulli Institute for Mathematics, Computer Science and Artificial Intelligence, University of Groningen + - name: Milla Valnet + affiliation: Sorbonne Université + - name: Ningning Xie + affiliation: University of Toronto; Google DeepMind + - name: Richard A. Eisenberg + affiliation: Jane Street + - name: Robert Blanco + affiliation: Max Planck Institute for Security and Privacy (MPI-SP) + - name: Simmo Saan + affiliation: University of Tartu, Estonia + - name: Takafumi Saikawa + affiliation: Nagoya University + - name: Troels Henriksen + affiliation: University of Copenhagen +--- + +OCaml Workshop 2024 took place during ICFP 2024, in Milan, Italy. + +ACM Sigplan ICFP page: [OCaml Workshop 2024](https://icfp24.sigplan.org/home/ocaml-2024) + +The OCaml Users and Developers Workshop brings together the OCaml community, including users of OCaml in industry, academia, hobbyists, and the free software community. + +Video recordings can be found on the [@OCamlWorkshops YouTube Channel](https://www.youtube.com/@OCamlWorkshops). + diff --git a/data/conferences/2025-ocaml-users-and-developers-workshop.md b/data/conferences/2025-ocaml-users-and-developers-workshop.md new file mode 100644 index 0000000000..330ce3192a --- /dev/null +++ b/data/conferences/2025-ocaml-users-and-developers-workshop.md @@ -0,0 +1,23 @@ +--- +title: OCaml Workshop 2025 +date: 2025-10-17 +location: Singapore +important_dates: + - date: 2025-07-03 + info: Abstract submission deadline + - date: 2025-08-07 + info: Author notification + - date: 2025-10-17 + info: OCaml Workshop +presentations: [] +organising_committee: [] +program_committee: [] +--- + +OCaml Workshop 2025 will take place during ICFP 2025, in Singapore. + +ACM Sigplan ICFP page: [OCaml Workshop 2025](https://conf.researchr.org/home/icfp-splash-2025/ocaml-2025) + +The OCaml Users and Developers Workshop brings together the OCaml community, including users of OCaml in industry, academia, hobbyists, and the free software community. + +Video recordings can be found on the [@OCamlWorkshops YouTube Channel](https://www.youtube.com/@OCamlWorkshops). diff --git a/data/cookbook/salt-and-hash-password-with-argon2/00-hashargon2.ml b/data/cookbook/salt-and-hash-password-with-argon2/00-hashargon2.ml new file mode 100644 index 0000000000..3b8a1f70a0 --- /dev/null +++ b/data/cookbook/salt-and-hash-password-with-argon2/00-hashargon2.ml @@ -0,0 +1,54 @@ +--- +packages: +- name: argon2 + tested_version: "1.0.2" + used_libraries: + - argon2 +--- + +(* Configuration for password hashing based on OWASP recommendations and Argon2 + default values. Note this example uses only the recommended "Argon2id" + variation. + References: + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + - https://github.com/P-H-C/phc-winner-argon2 *) +let t_cost = 2 and + m_cost = 65536 and + parallelism = 1 and + hash_len = 32 and + salt_len = 10 + +(* The hash output length. *) +let encoded_len = + Argon2.encoded_len ~t_cost ~m_cost ~parallelism ~salt_len ~hash_len ~kind:ID + +(* Generate a salt string for a given length using only characters in the range + "A-Z". This is a simplistic generator and should be replaced with + cryptographically secure random number generator ("mirage-crypto", for + example). *) +let gen_salt len = + let rand_char _ = 65 + (Random.int 26) |> char_of_int in + String.init len rand_char + +(* Return an encoded hash string for the given password. The encoded password + contains the required metadata for future verification. *) +let hash_password passwd = + Result.map Argon2.ID.encoded_to_string + (Argon2.ID.hash_encoded + ~t_cost ~m_cost ~parallelism ~hash_len ~encoded_len + ~pwd:passwd ~salt:(gen_salt salt_len)) + +(* Verifie if the encoded hash string matches the given password. *) +let verify encoded_hash pwd = + match Argon2.verify ~encoded:encoded_hash ~pwd ~kind:ID with + | Ok true_or_false -> true_or_false + | Error VERIFY_MISMATCH -> false + | Error e -> raise (Failure (Argon2.ErrorCodes.message e)) + +let () = + let hashed_pwd = Result.get_ok (hash_password "my insecure password") in + Printf.printf "Hashed password: %s\n" hashed_pwd; + let fst_attempt = "my secure password" in + Printf.printf "'%s' is correct? %B\n" fst_attempt (verify hashed_pwd fst_attempt); + let snd_attempt = "my insecure password" in + Printf.printf "'%s' is correct? %B\n" snd_attempt (verify hashed_pwd snd_attempt) diff --git a/data/cookbook/sorting-lists-and-arrays/00-stdlib.ml b/data/cookbook/sorting-lists-and-arrays/00-stdlib.ml index 4e18b2e19b..75652b788e 100644 --- a/data/cookbook/sorting-lists-and-arrays/00-stdlib.ml +++ b/data/cookbook/sorting-lists-and-arrays/00-stdlib.ml @@ -6,7 +6,7 @@ packages: [] **Note:** The `compare` function is polymorphic and works over all types. *) let l = [ 1; 90; 42; 27 ] -let l' = List.sort compare a +let l' = List.sort compare l (* Sorting an array while modifying it in place. *) let a = [| 1; 90; 42; 27 |] diff --git a/data/cookbook/tasks.yml b/data/cookbook/tasks.yml index a359210ac9..bb78481a4c 100644 --- a/data/cookbook/tasks.yml +++ b/data/cookbook/tasks.yml @@ -56,6 +56,8 @@ categories: slug: calculate-sha-256-digest-of-file - title: Sign and Verify a Message With an HMAC Digest slug: sign-and-verify-hmac-digest + - title: Salt and Hash a Password With Argon2 + slug: salt-and-hash-password-with-argon2 - title: Salt and Hash a Password With PBKDF2 slug: salt-and-hash-password-with-pkgdf2 - title: Data Structures & Algorithms diff --git a/data/events/2025-10-17-ocaml-workshop.md b/data/events/2025-10-17-ocaml-workshop.md new file mode 100644 index 0000000000..bd516b8bd1 --- /dev/null +++ b/data/events/2025-10-17-ocaml-workshop.md @@ -0,0 +1,13 @@ +--- +title: "OCaml Users and Developers Workshop 2025" +event_type: conference +country: "Singapore" +city: "Singapore" +url: https://conf.researchr.org/home/icfp-splash-2025/ocaml-2025#Call-for-Presentations +starts: + yyyy_mm_dd: "2025-10-17" +submission_deadline: + yyyy_mm_dd: "2025-07-03" +author_notification_date: + yyyy_mm_dd: "2025-08-07" +--- diff --git a/data/governance.yml b/data/governance.yml index 62841e3eca..83a0fe8011 100644 --- a/data/governance.yml +++ b/data/governance.yml @@ -127,6 +127,9 @@ teams: - name: Stephen Sherratt github: gridbugs role: Maintainer + - name: Etienne Marais + github: maiste + role: Maintainer - name: Antonio Nuno Monteiro github: anmonteiro role: Maintainer @@ -195,12 +198,12 @@ teams: - name: Ulysse github: voodoos role: Maintainer - - name: Rafał Gwoździński - github: 3Rafal - role: Maintainer - name: Xavier Van de Woestyne github: xvw role: Maintainer + - name: Muluh Godson + github: PizieDust + role: Maintainer - id: merlin-dev name: Merlin description: Context sensitive completion for OCaml in Vim and Emacs @@ -220,8 +223,8 @@ teams: - name: Ulysse Gérard github: voodoos role: Maintainer - - name: Sonja Heinze - github: pitag-ha + - name: Muluh Godson + github: PizieDust role: Maintainer - name: "Fr\xE9d\xE9ric Bour" github: let-def @@ -254,21 +257,12 @@ teams: - name: Leo White github: lpw25 role: Maintainer - - name: Thomas Refis - github: trefis - role: Maintainer - name: Jules Aguillon github: Julow role: Maintainer - name: Paul-Elliot Anglès D'Auriac github: panglesd role: Maintainer - - name: Emile Trotignon - github: EmileTrotignon - role: Maintainer - - name: Guillaume Petiot - github: gpetiot - role: Maintainer - id: ppxlib-dev name: Ppxlib description: Base library and tools for PPX rewriters @@ -283,6 +277,12 @@ teams: calendar: https://calendar.google.com/calendar/u/4?cid=Y19iMDA5ZDA4MDg0YzIwYWMzMDQ4NjJhN2FkZWJiYjdmOTU0NGIxYzEwMmU0MDMyMTAzMDFiY2ZhYjcwMDBmMjNlQGdyb3VwLmNhbGVuZGFyLmdvb2dsZS5jb20 notes: https://github.com/ocaml-ppx/ppxlib/wiki members: + - name: Patrick Ferris + github: patricoferris + role: Maintainer + - name: Nathan Rebours + github: NathanReb + role: Maintainer - name: Sonja Heinze github: pitag-ha role: Maintainer diff --git a/data/industrial_users/ocamlpro.md b/data/industrial_users/ocamlpro.md index 62f370eb79..f5272f24f3 100644 --- a/data/industrial_users/ocamlpro.md +++ b/data/industrial_users/ocamlpro.md @@ -1,13 +1,21 @@ --- name: OCamlPro description: > - OCamlPro develops and maintains a development environment for the OCaml language. + OCamlPro helps its clients use OCaml and Rust in their business applications, thanks to a team of experts in programming languages, software development and algorithms. OCamlPro created opam, and maintains the Flambda optimizing compilers. url: "https://www.ocamlpro.com" logo: users/ocamlpro.svg locations: - - France + - "Paris, France" consortium: true featured: false --- -OCamlPro develops and maintains a development environment for the OCaml language. They provide services for companies deciding to use OCaml. Among these services: trainings, necessary expertise, tools and libraries long-term support, and specific developments to their applicative domains. \ No newline at end of file +OCamlPro was created in 2011 to promote the use of languages with formal grounds and strong static typing, such as OCaml and Rust, thanks to a strong connection with both academia and industry. Along the years, OCamlPro has participated in many projects for the OCaml community and for its clients: + + - tooling for OCaml developers, such as the Opam package manager or the Flambda optimizing compilers, + - development of complex software, such as the prototype and ICO platform of the Tezos blockchain, + - new languages/DSLs and tooling for other languages, such as the SuperBOL LSP for COBOL on Vscode or OWI for WebAssembly symbolic testing, + - code analyzis and code verification, such as the Alt-Ergo SMT solver or the SeaCoral unittest generator, + - audits, consulting and support + - training in OCaml and Rust + diff --git a/data/industrial_users/r2c.md b/data/industrial_users/r2c.md deleted file mode 100644 index 15ef328c1d..0000000000 --- a/data/industrial_users/r2c.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -name: r2c -description: > - r2c is a VC-funded security company headquartered in San Francisco and distributed worldwide -url: "https://r2c.dev" -logo: users/r2c.png -locations: - - California, United States -consortium: false -featured: false ---- - -r2c is a VC-funded security company headquartered in San Francisco and distributed worldwide. The main product as of 2021 is [Semgrep](https://semgrep.dev/), an open-source,syntax-aware grep that supports many languages. OCaml is used extensively for parsing and analyzing source code. - -Semgrep was originally open-sourced at Facebook and its roots lie in the Linux refactoring tool, [Coccinelle](https://web.archive.org/web/20230408035503/https://coccinelle.gitlabpages.inria.fr/website/). r2c continues Semgrep’s development and is [hiring software engineers](https://www.lever.co/careers/) who specialize in program analysis. \ No newline at end of file diff --git a/data/industrial_users/semgrep.md b/data/industrial_users/semgrep.md new file mode 100644 index 0000000000..3da95be415 --- /dev/null +++ b/data/industrial_users/semgrep.md @@ -0,0 +1,15 @@ +--- +name: Semgrep +description: > + Semgrep is a security company headquartered in San Francisco and distributed worldwide +url: "https://semgrep.dev" +logo: users/semgrep.png +locations: + - California, United States +consortium: false +featured: false +--- + +Semgrep is a security company headquartered in San Francisco and distributed worldwide. The main product as of 2025 is the [Semgrep Cloud Platform](https://semgrep.dev/), an application security platform, and the open-source `semgrep` tool, a syntax-aware semantic grep that supports many languages. OCaml is used extensively in the `semgrep` tool for parsing and analyzing source code. + +`semgrep` was originally open-sourced at Facebook and its roots lie in the Linux refactoring tool, [Coccinelle](https://web.archive.org/web/20230408035503/https://coccinelle.gitlabpages.inria.fr/website/). Semgrep continues development of the open-source tool and is [hiring software engineers](https://semgrep.dev/about/careers/#job-board) who specialize in program analysis. \ No newline at end of file diff --git a/data/is_ocaml_yet/gui.md b/data/is_ocaml_yet/gui.md index 25ea82869d..6679d22aaa 100644 --- a/data/is_ocaml_yet/gui.md +++ b/data/is_ocaml_yet/gui.md @@ -4,7 +4,7 @@ question: Is OCaml GUI Yet? answer: Not quite yet, but we're getting there! categories: - name: Frameworks - status: 🟡 + status: • description: | These libraries provide a rich toolkit to develop GUI applications. packages: @@ -14,7 +14,7 @@ categories: - name: tsdl - name: sfml - name: 3d graphics - status: 🟡 + status: • description: | These are libraries that are for manipulating 3D graphics. They offer a wide range of functionalities, including geometric transformations, rendering, shading, and handling user input. packages: @@ -22,7 +22,7 @@ categories: - name: glMLite - name: irrlicht - name: 2d graphics - status: 🟡 + status: • description: | These libraries provides the necessary functionalities to create and manipulate 2D graphics. packages: @@ -31,7 +31,7 @@ categories: - name: async_graphics - name: cairo2 - name: image processing - status: 🟢 + status: • description: | Packages for image-processing. packages: @@ -39,7 +39,7 @@ categories: - name: bimage - name: ocamlsdl2-image - name: Plotting - status: 🟢 + status: • description: | These libraries are used to create visual representations of data. They provide functionalities to generate various types of plots, charts, and diagrams. packages: @@ -51,7 +51,7 @@ categories: - name: plplot - name: plotly - name: Events - status: 🟡 + status: • description: | These libraries are used to handle events, which are signals or occurrences in the program’s environment that require a specific action or response. packages: diff --git a/data/is_ocaml_yet/web.md b/data/is_ocaml_yet/web.md index 4bea825304..87d8b7bc8c 100644 --- a/data/is_ocaml_yet/web.md +++ b/data/is_ocaml_yet/web.md @@ -4,7 +4,7 @@ question: Is OCaml Web Yet? answer: Yes, but some parts are still missing categories: - name: Web Frameworks - status: 🟡 + status: • description: | Web development frameworks for building OCaml Web applications. packages: @@ -14,7 +14,7 @@ categories: - name: sihl - name: ocsigen-start - name: Browser - status: 🟢 + status: • description: | OCaml has excellent support for running in the browser! The [Js_of_ocaml](/p/js_of_ocaml/latest) compiler, which translates OCaml into JavaScript, is a well-established tool dating back to 2010. It integrates seamlessly with the existing OCaml ecosystem and powers numerous production applications. @@ -34,7 +34,7 @@ categories: - name: ocaml-vdom - name: fmlib_browser - name: WebAssembly - status: 🟡 + status: • description: | Packages and tools for compiling OCaml code to WebAssembly. packages: @@ -49,7 +49,7 @@ categories: - name: wasm - name: owi - name: Lower Web-Stack - status: 🟡 + status: • description: | Packages that provide foundational networking and communication capabilities. packages: @@ -73,7 +73,7 @@ categories: - name: mimic - name: tiny_httpd - name: HTTP Clients - status: 🔴 + status: • description: | HTTP client libraries for making HTTP requests. packages: @@ -83,7 +83,7 @@ categories: - name: http-lwt-client - name: ezcurl - name: Templating - status: 🟡 + status: • description: | Packages that assist in generating dynamic HTML or text content. packages: @@ -94,7 +94,7 @@ categories: - name: mustache - name: jingoo - name: Static Site Generation - status: 🟡 + status: • description: | Packages for generating static websites. packages: @@ -112,7 +112,7 @@ categories: url: https://github.com/ocsigen/html_of_wiki synopsis: Static website generator for software projects - name: Mobile apps - status: 🟡 + status: • description: Packages for creating mobile applications packages: - name: eliom @@ -162,7 +162,7 @@ categories: - name: cordova-plugin-vibration - name: cordova-plugin-videoplayer - name: Authentication - status: 🔴 + status: • description: | Packages for authentication-related functionality in OCaml Web applications. packages: @@ -176,7 +176,7 @@ categories: - name: oidc - name: spoke - name: Binary protocols - status: 🟡 + status: • description: | There are implementations for a lot of popular protocols, some of them are solid, but some of them are still incomplete and need more testing. Some useful protocols for which there is no package include FlatBuffers and AMQP. packages: @@ -193,7 +193,7 @@ categories: - name: mqtt - name: msgpck - name: Database - status: 🟠 + status: • description: | Database-related packages for interacting with databases in OCaml Web applications, from simple connectors to type-safe SQL wrappers. packages: @@ -210,14 +210,14 @@ categories: - name: sqlgg - name: mariadb - name: Internationalization - status: 🆘 + status: • description: | Internationalization and localization for OCaml applications. packages: - name: gettext - name: ocsigen-i18n - name: Message Queues & Key-Value Stores - status: 🆘 + status: • description: | Packages for interacting with popular message queues and key-value stores. packages: @@ -226,7 +226,7 @@ categories: - name: redis - name: zmq - name: Serializers - status: 🟡 + status: • description: | Packages for serializing and deserialising data in different formats. packages: @@ -246,7 +246,7 @@ categories: - name: csexp - name: data-encoding - name: Syndication/RSS - status: 🟡 + status: • description: | Packages for syndicating content and working with RSS feeds. packages: @@ -254,7 +254,7 @@ categories: - name: river - name: rss - name: External Web APIs - status: 🆘 + status: • description: | Packages that provide OCaml bindings and clients for interacting with external Web APIs. packages: @@ -302,7 +302,7 @@ categories: url: https://github.com/besport/ocaml-js-video-players synopsis: Add different video players to your OCaml Web or mobile app (Youtube, Dailymotion, Vimeo) - name: Logging - status: 🟠 + status: • description: | Packages for logging and monitoring that assist in tracking application behavior and performance. packages: @@ -313,7 +313,7 @@ categories: - name: opentelemetry - name: prometheus - name: Email - status: 🟠 + status: • description: | Packages for sending and managing email communications. packages: @@ -329,7 +329,7 @@ categories: - name: dkim - name: uspf - name: Compression - status: 🟡 + status: • description: | Packages that enable compression and decompression of data in OCaml Web applications. packages: @@ -346,7 +346,7 @@ categories: - name: zstandard - name: carton - name: Cryptography - status: 🟡 + status: • description: | Packages for secure communication, encryption, hashing, and other cryptographic operations. packages: @@ -365,7 +365,7 @@ categories: - name: dirsp-proscript - name: digestif - name: En- & Decoding - status: 🟠 + status: • description: | Encoding and decoding various data formats. packages: diff --git a/data/media/academic_institution/ashoka.png b/data/media/academic_institution/ashoka.png new file mode 100644 index 0000000000..d2537eefd8 Binary files /dev/null and b/data/media/academic_institution/ashoka.png differ diff --git a/data/media/academic_institution/bits-pillani-2-1.png b/data/media/academic_institution/bits-pillani-2-1.png new file mode 100644 index 0000000000..9e4d9f420b Binary files /dev/null and b/data/media/academic_institution/bits-pillani-2-1.png differ diff --git a/data/media/books/learn-programming-with-ocaml.jpg b/data/media/books/learn-programming-with-ocaml.jpg new file mode 100644 index 0000000000..77be1a4981 Binary files /dev/null and b/data/media/books/learn-programming-with-ocaml.jpg differ diff --git a/data/media/tutorials/emacs-type-info.gif b/data/media/tutorials/emacs-type-info.gif old mode 100755 new mode 100644 index b64fa66020..5a7ced51e9 Binary files a/data/media/tutorials/emacs-type-info.gif and b/data/media/tutorials/emacs-type-info.gif differ diff --git a/data/media/users/r2c.png b/data/media/users/r2c.png deleted file mode 100644 index 5208b5a796..0000000000 Binary files a/data/media/users/r2c.png and /dev/null differ diff --git a/data/media/users/semgrep.png b/data/media/users/semgrep.png new file mode 100644 index 0000000000..6cc54dce8b Binary files /dev/null and b/data/media/users/semgrep.png differ diff --git a/data/news/platform/platform-2023-10.md b/data/news/platform/platform-2023-10.md index beceec02a7..bbb4075ed6 100644 --- a/data/news/platform/platform-2023-10.md +++ b/data/news/platform/platform-2023-10.md @@ -97,7 +97,7 @@ In this October edition, we bring you the latest on the OCaml Platform, continui **Why:** Project-wide reference as an editor feature is a great way for developers to navigate their codebase and understand it better. It's also a feature that users expect to have coming from other ecosystems, so having support for it in Merlin and OCaml LSP will both improve OCaml editor experience and make it on par with other languages. -**What:** We're adding a new `merlin single occurrences` command and support for the LSP `textDocument/references` request. To do that, we're extending the compiler's Shapes to support global occurences, building a tool that generates an index of identifiers in a codebase and adding support for it in Dune, Merlin, and OCaml LSP. +**What:** We're adding a new `merlin single occurrences` command and support for the LSP `textDocument/references` request. To do that, we're extending the compiler's Shapes to support global occurrences, building a tool that generates an index of identifiers in a codebase and adding support for it in Dune, Merlin, and OCaml LSP. **Activities:** - We continued working on the compiler PR for project-wide occurrences, notably adding support for inline records' labels. The PR is now ready for the next round of reviews. -- [ocaml/ocaml#12508](https://github.com/ocaml/ocaml/pull/12508) diff --git a/data/news/platform/platform-2023-12.md b/data/news/platform/platform-2023-12.md index ed1eb6a46e..f803c95009 100644 --- a/data/news/platform/platform-2023-12.md +++ b/data/news/platform/platform-2023-12.md @@ -85,7 +85,7 @@ In this November and December edition, we are excited to bring you the latest on **Activities:** - After merging [the PR that added support for search to `odoc`](https://github.com/ocaml/odoc/pull/972) in October, we continued work on building an `odoc`-compatible search engine based on [Sherlodoc](https://doc.sherlocode.com/). This will give a search engine with type-based search for every package that uses `odoc`. The plan is to make Sherlodoc the search engine in Dune's documentation generation. You can try an early demo on [Varray's doc](https://art-w.github.io/varray/varray/Varray) -- [art-w/sherlodoc#4](https://github.com/art-w/sherlodoc/pull/4) -- Buiding on `odoc`'s support for search, we merged a PR that adds occurrences information to the search index. This will allows `odoc` search engines to improve the order of search results by using the number of occurences. -- [ocaml/odoc#976](https://github.com/ocaml/odoc/pull/976) +- Buiding on `odoc`'s support for search, we merged a PR that adds occurrences information to the search index. This will allows `odoc` search engines to improve the order of search results by using the number of occurrences. -- [ocaml/odoc#976](https://github.com/ocaml/odoc/pull/976) ## **[`odoc`]** Syntax for Images and Assets in `odoc` ([W25](https://ocaml.org/docs/platform-roadmap#w25-generate-documentation)) @@ -152,4 +152,4 @@ In this November and December edition, we are excited to bring you the latest on - We've added information about the size of the major heap at the end of an `ocamlmerlin` query - [#1717](https://github.com/ocaml/merlin/pull/1717) - We've finished up Merlin's new Fuzzy CI, a by-product of the performance work. - We've opened the PRs - [#1716](https://github.com/ocaml/merlin/pull/1716) (and [#1719](https://github.com/ocaml/merlin/pull/1719)) - - We've written a GitHub wiki entry with a high-level description about it. - [Merlin Fuzzy CI](https://github.com/ocaml/merlin/wiki/Merlin-Fuzzy-CI) \ No newline at end of file + - We've written a GitHub wiki entry with a high-level description about it. - [Merlin Fuzzy CI](https://github.com/ocaml/merlin/wiki/Merlin-Fuzzy-CI) diff --git a/data/news/platform/platform-2024-12.md b/data/news/platform/platform-2024-12.md new file mode 100644 index 0000000000..df5260a04d --- /dev/null +++ b/data/news/platform/platform-2024-12.md @@ -0,0 +1,190 @@ +--- +title: "Platform Newsletter: September 2024 - January 2025" +description: Update from the OCaml Platform. +date: "2025-03-04" +tags: [platform] +--- + +Welcome to the thirteenth edition of the OCaml Platform newsletter! + +In this September 2024 - January 2025 edition, we are excited to bring you the latest on the OCaml Platform, continuing our tradition of highlighting recent developments as seen in [previous editions](https://discuss.ocaml.org/tag/platform-newsletter). To understand the direction we're headed, especially regarding development workflows and user experience improvements, check out our [roadmap](https://ocaml.org/docs/platform-roadmap). + +**Highlights:** +* **Dune Enables Cache By Default, Adds WebAssembly Support** +The latest Dune releases mark significant progress in build performance and language support. Version 3.17.0 enables the Dune cache by default for known-safe operations, improving build times for common tasks. The addition of Wasm_of_ocaml support opens new possibilities for OCaml projects targeting the web or other WebAssembly runtimes. In addition, Dune now supports adding Codeberg and GitLab repositories via the `(source)` stanza. +* **opam 2.3.0** +As announced with opam 2.2, opam releases are now time-based with a cadence of 6 months. Opam 2.3 has been released last November. It contains a major breaking change regarding extra-files handling: extra-files are now ignored when they are not present in the opam file. Previously they were silently added. This release adds also some new commands like `opam list --latest-only` or `opam install foo --verbose-on bar`, among other fixes and enhancements. +* **Improved Editor Workflows with OCaml-LSP and Merlin** +A major milestone for project-wide features has been reached with the release of OCaml 5.3: LSP's renaming feature now [_renames symbols in the entire project_](https://discuss.ocaml.org/t/ann-merlin-and-ocaml-lsp-support-experimental-project-wide-renaming/16008) if the index is built. Additionally,all of the classic merlin-server commands are now available as LSP custom requests: this enabled the addition of [many new features to the Visual Studio Code plugin](https://tarides.com/blog/2025-02-28-full-blown-productivity-in-vscode-with-ocaml/). Finally a brand new Emacs mode, based on LSP and the new custom queries is [now available on Melpa](https://melpa.org/#/ocaml-eglot). +* **Performance and Security Enhancements** +Recent updates across the platform focus on performance and reliability. Dune optimized its handling of .cmxs files, while opam implemented stricter git submodule error checking. OCaml-LSP resolved file descriptor leaks, contributing to a more stable development environment. + +**Feature Guides & Announcements:** + +* [[ANN] Odoc 3 Beta Release](https://discuss.ocaml.org/t/ann-odoc-3-beta-release/16043) +* [[ANN] Merlin and OCaml-LSP support experimental project-wide renaming](https://discuss.ocaml.org/t/ann-merlin-and-ocaml-lsp-support-experimental-project-wide-renaming/16008) +* [[ANN] Release of ocaml-eglot 1.0.0](https://discuss.ocaml.org/t/ann-release-of-ocaml-eglot-1-0-0/15978) +* [[ANN] ppxlib.034.0](https://discuss.ocaml.org/t/ann-ppxlib-034-0/15952) +* [Installing Developer Tools with Dune](https://ocaml.org/changelog/2024-11-15-installing-developer-tools-with-dune) +* [Shell Completions in Dune Developer Preview](https://ocaml.org/changelog/2024-10-29-shell-completions-in-dune-developer-preview) +* [OCaml Infrastructure: Enhancing Platform Support and User Experience](https://ocaml.org/changelog/2024-10-02-updates) +* [Call for Feedback](https://ocaml.org/changelog/2024-09-25-call-for-feedback) + +**Releases:** + +* [Dune 3.17.2](https://ocaml.org/changelog/2025-01-23-dune.3.17.2) +* [Release of OCaml 5.3.0](https://ocaml.org/changelog/2025-01-08-ocaml-5.3.0) +* [OCaml-LSP 1.20.1](https://ocaml.org/changelog/2024-12-23-ocaml-lsp-1.20.1) +* [opam-publish 2.5.0](https://github.com/ocaml-opam/opam-publish/releases/tag/2.5.0) +* [Merlin 5.3-502 for OCaml 5.2 and 4.18-414 for OCaml 4.14](https://ocaml.org/changelog/2024-12-23-merlin-5.3.502-and-4.18.414) +* [Dune 3.17.1](https://ocaml.org/changelog/2024-12-18-dune.3.17.1) +* [OCamlformat 0.27.0](https://ocaml.org/changelog/2024-12-02-ocamlformat-0.27.0) +* [Dune 3.17.0](https://ocaml.org/changelog/2024-11-27-dune.3.17.0) +* [opam 2.3.0](https://ocaml.org/changelog/2024-11-13-opam-2-3-0) +* [Dune 3.16.1](https://ocaml.org/changelog/2024-10-30-dune.3.16.1) +* [Merlin 5.2.1-502 for OCaml 5.2 and 4.17.1 for OCaml 5.1 and 4.14](https://ocaml.org/changelog/2024-09-27-merlin-5.2.1) + +## **Dune** + +**Roadmap:** [Develop / (W4) Build a Project](https://ocaml.org/docs/platform-roadmap#w4-build-a-project) + +[Dune 3.17 was released](https://discuss.ocaml.org/t/ann-dune-3-17/15770) with significant improvements to package management. Key features include binary distribution support, better error messages for missing packages, and Windows support without requiring OPAM. + +The [Dune Developer Preview website](https://preview.dune.build) now provides editor setup instructions and package management tutorials. + +Dune's package management features [were tested across hundreds of packages](https://dune.check.ci.dev/) in the opam repository, and a coverage tool was developed to track build success rates. For local development, Dune added support for building dependencies via `@pkg-install`, caching for package builds, and automated binary builds of development tools. The system supports both monorepo and polyrepo workflows, with options for installing individual dependencies or complete development environments. + +The addition of [Wasm_of_ocaml support in Dune](https://github.com/ocaml/dune/pull/11093) opens new possibilities for OCaml projects targeting the web or other WebAssembly runtimes. + +**Activities:** +- Updated preview website with editor setup instructions at https://preview.dune.build and published binary installer providing prebuilt Dune binaries +- [Enable dune cache by default](https://github.com/ocaml/dune/pull/10710) +- [Added wasm_of_ocaml support](https://github.com/ocaml/dune/pull/11093) +- Added support for [Codeberg](https://github.com/ocaml/dune/pull/10904) and [GitLab organizations](https://github.com/ocaml/dune/pull/10766) in the `(source)` stanza +- [Added support for `-H` compiler flag](https://github.com/ocaml/dune/pull/10644) enabling better semantics for `(implicit_transitive_deps false)` + +**Maintained by:** Rudi Grinberg (@rgrinberg, Jane Street), Nicolás Ojeda Bär (@nojb, LexiFi), Marek Kubica (@Leonidas-from-XIV, Tarides), Etienne Millon (@emillon, Tarides), Stephen Sherratt (@gridbugs, Tarides), Antonio Nuno Monteiro (@anmonteiro), Étienne Marais (@maiste, Tarides) + +## **Editor Tools** + +**Roadmap:** [Edit / (W19) Navigate Code](https://ocaml.org/tools/platform-roadmap#w19-navigate-code), [Edit / (W20) Refactor Code](https://ocaml.org/tools/platform-roadmap#w20-refactor-code) + +Developer tooling received substantial upgrades during the end of last year and the beginning 2025. A major milestone for project-wide features has been reached with the release of OCaml 5.3: LSP's renaming feature now [_renames symbols in the entire project_](https://discuss.ocaml.org/t/ann-merlin-and-ocaml-lsp-support-experimental-project-wide-renaming/16008) if the index is built. Additionally, all of the classic merlin-server commands are now available as LSP custom requests: this enabled the addition of [many new features to the Visual Studio Code plugin](https://tarides.com/blog/2025-02-28-full-blown-productivity-in-vscode-with-ocaml/) and the creation of a brand new Emacs mode, based on LSP, [now available on Melpa](https://melpa.org/#/ocaml-eglot). + +These features bring OCaml editor support closer to modern IDE capabilities, with implementations available across multiple editors. + +### Merlin and OCaml LSP Server + +Support for project wide renaming, search-by-type, and ocaml-lsp-server now exposes all Merlin features via LSP custom queries. + +**Notable Activity** +- OCaml 5.3 support ([merlin#1850](https://github.com/ocaml/merlin/pull/1850)) +- Project-wide renaming is now available. ([ocaml-lsp#1431](https://github.com/ocaml/ocaml-lsp/pull/1431) and [merlin#1877](https://github.com/ocaml/merlin/pull/1877)) +- A new option to mute hover responses has been added for better integration with alternative hover providers ([ocaml-lsp#1416](https://github.com/ocaml/ocaml-lsp/pull/1416)) +- New type-based search support similar to Hoogle ([ocaml-lsp#1369](https://github.com/ocaml/ocaml-lsp/pull/1369) and [merlin#1828](https://github.com/ocaml/merlin/pull/1828)) + +**Bug Fixes** +- Fixed completion range issues with polymorphic variants ([ocaml-lsp#1427](https://github.com/ocaml/ocaml-lsp/issues/1427)) +- Fixed various issues with jump code actions and added customization options ([ocaml-lsp#1376](https://github.com/ocaml/ocaml-lsp/pull/1376)) +- Various fixes and improvements have been made to signature help and inlay hints + +### Visual Studio Code plugin + +Added support for most of the Merlin features historically availbale to Emacs and Vim users, via the new LSP custom requests. + +**Notable Activity** + +- Improved typed-of-selection feature, with ability to grow or shrink the selection and increase verbosity ([#1675](https://github.com/ocamllabs/vscode-ocaml-platform/pull/1675)). +- Improved jump navigation ([#1654](https://github.com/ocamllabs/vscode-ocaml-platform/pull/1654)), search-by-type ([#1626](https://github.com/ocamllabs/vscode-ocaml-platform/pull/1626)) +- Improved typed holes navigation ([#1666](https://github.com/ocamllabs/vscode-ocaml-platform/pull/1666)). +- New search-by-type command ([#1626](https://github.com/ocamllabs/vscode-ocaml-platform/pull/1626)). + +**OCaml LSP Server maintained by:** Ulysse Gérard (@voodoos, Tarides), Xavier Van de Woestyne (@xvw, Tarides), Rudi Grinberg (@rgrinberg, Jane Street) + +**Merlin maintained by:** Ulysse Gérard (@voodoos, Tarides), Xavier Van de Woestyne (@xvw, Tarides) + +### Emacs support + +A brand new Emacs plugin based on the Eglot LSP client is now ready for daily usage: https://github.com/tarides/ocaml-eglot. + +## **Documentation Tools** + +**Roadmap:** [Share / (W25) Generate Documentation](https://ocaml.org/tools/platform-roadmap#w25-generate-documentation) + +### Odoc + +**Maintained by:** Jon Ludlam (@jonludlam, Tarides), Daniel Bünzli (@dbuenzli), Jules Aguillon (@julow, Tarides), Paul-Elliot Anglès d'Auriac (@panglesd, Tarides), Emile Trotignon (@EmileTrotignon, Tarides, then Ahrefs) + +There is now a [beta release for odoc 3](https://discuss.ocaml.org/t/ann-odoc-3-beta-release/16043) that you can try out and give feedback on! + +During the quarter, odoc has been making steady progress toward its 3.0 release with several notable improvements: +- **Enhanced Navigation**: The sidebar and breadcrumbs navigation has been unified and improved ([#1251](https://github.com/ocaml/odoc/pull/1251)), making the documentation hierarchy more consistent and flexible. This allows better organization of modules, pages, and source files in the documentation. +- **Documentation Features**: New features have been added to Odoc 3 ([#1264](https://github.com/ocaml/odoc/pull/1264)), including: + - Support for images with embedded assets + - Cross-package linking (linking to modules from external libraries) +- **Search Integration**: Sherlodoc, the search functionality, has been merged into the main odoc codebase ([#1263](https://github.com/ocaml/odoc/pull/1263)), ensuring better maintenance and synchronized releases. + +**Notable Activity** +- [[ANN] Odoc 3 Beta Release](https://discuss.ocaml.org/t/ann-odoc-3-beta-release/16043) + +### Mdx upgraded to OCaml 5.3 + +**Maintained by:** Marek Kubica (@Leonidas-from-XIV, Tarides), Thomas Gazagnaire (@samoht, Tarides) + +With OCaml 5.3, some compiler error messages changed, so MDX was updated to use a more expressive tag system to choose which version of the compiler can run which code block. This effort uncovered a bug in the current handling of skipped blocks for `mli` files, which was fixed. + +**Notable Activity** + - OCaml 5.3 support ([#457](https://github.com/realworldocaml/mdx/pull/457)), ensuring the tool remains compatible with the latest OCaml releases. + - Fixed error handling for skipped blocks in `mli` files ([#462](https://github.com/realworldocaml/mdx/pull/462)) + - Improved syntax highlighting ([#461](https://github.com/realworldocaml/mdx/pull/461)) + - Added support for multiple version labels ([#458](https://github.com/realworldocaml/mdx/pull/458)), improving the ability to test code across different OCaml versions. + +## **Package Management** + +### Opam + +[Opam 2.3.0 was released in November](https://ocaml.org/changelog/2024-11-13-opam-2-3-0). We are now working towards the 2.4 release, with some new sub commands (`admin`, `source`, `switch`, etc.), fixes (pinning, switch, software heritage fallback, UI) and enhancements. + +**Notable Activity** +- Add several checksum, `extra-files` and `extra-source` lints - [#5561](https://github.com/ocaml/opam/issues/5561) +- Add options `opam source --require-checksums` and `--no-checksums` to harmonise with `opam install` - [#5563](https://github.com/ocaml/opam/issues/5563) +- Add the current VCS revision information to `opam pin list` - [#6274](https://github.com/ocaml/opam/issues/6274) - fix [#5533](https://github.com/ocaml/opam/issues/5533) +- Make opamfile parsing more robust for future changes - [#6199](https://github.com/ocaml/opam/issues/6199) - fix [#6188](https://github.com/ocaml/opam/issues/6188) +- Fix `opam switch remove ` failure when it is a linked switch - [#6276](https://github.com/ocaml/opam/issues/6276) - fix [#6275](https://github.com/ocaml/opam/issues/6275) +- Fix `opam switch list-available` when given several arguments - [#6318](https://github.com/ocaml/opam/issues/6318) +- Correctly handle `pkg.version` pattern in `opam switch list-available` - [#6186](https://github.com/ocaml/opam/issues/6186) - fix [#6152](https://github.com/ocaml/opam/issues/6152) +- Fix sandbox for NixOS [#6333](https://github.com/ocaml/opam/issues/6333), and `DUNE_CACHE_ROOT` environment variabale usage - [#6326](https://github.com/ocaml/opam/issues/6326) +- Add `opam admin compare-versions` to ease version comparison for sanity checks [#6197](https://github.com/ocaml/opam/issues/6197) and fix `opam admin check` in the presence of some undefined variables - [#6331](https://github.com/ocaml/opam/issues/6331) - fix [#6329](https://github.com/ocaml/opam/issues/6329) +- When loading a repository, don’t automatically populate `extra-files:` field with found files in `files/` - [#5564](https://github.com/ocaml/opam/issues/5564) +- Update and fix Software Heritage fallback - [#6036](https://github.com/ocaml/opam/issues/6036) - fix [#5721](https://github.com/ocaml/opam/issues/5721) +- Warn if a repository to remove doesn’t exist - [#5014](https://github.com/ocaml/opam/issues/5014) - fix [#5012](https://github.com/ocaml/opam/issues/5012) +- Silently mark packages requiring an unsupported version of opam as unavailable - [#5665](https://github.com/ocaml/opam/issues/5665) - fix [#5631](https://github.com/ocaml/opam/issues/5631) +- Display switch invariant with the same syntax that it is written in file (no pretty printing) - [#5619](https://github.com/ocaml/opam/issues/5619) - fix [#5491](https://github.com/ocaml/opam/issues/5491) +- Fix output display regarding terminal size [#6244](https://github.com/ocaml/opam/issues/6244) - fix [#6243](https://github.com/ocaml/opam/issues/6243) +- Change default answer display - [#6289](https://github.com/ocaml/opam/issues/6289) - fix [#6288](https://github.com/ocaml/opam/issues/6288) +- Add a warning when setting a variable with `opam var` if an option is shadowed - [#4904](https://github.com/ocaml/opam/issues/4904) - fix [#4730](https://github.com/ocaml/opam/issues/4730) +- Improve the error message when a directory is not available while fetching using rsync - [#6027](https://github.com/ocaml/opam/issues/6027) +- Fix `install.exe` search path on Windows - [#6190](https://github.com/ocaml/opam/issues/6190) +- Add `ALTLinux` support for external dependencies - [#6207](https://github.com/ocaml/opam/issues/6207) +- Make `uname` information more robust accros ditributions - [#6127](https://github.com/ocaml/opam/issues/6127) + +**Maintained by:** Raja Boujbel (@rjbou - OCamlPro), Kate Deplaix (@kit-ty-kate, Ahrefs), David Allsopp (@dra27, Tarides) + +### Dune-release + +**Roadmap:** [Share / (W26) Package Publication](https://ocaml.org/tools/platform-roadmap#w26-package-publication) + +Dune-release has been improved to better handle publishing packages from custom repositories and private Git repositories. + +**Notable Activity** +- Support for overwriting the dev-repo field when creating GitHub tags/releases ([#494](https://github.com/tarides/dune-release/pull/494)), which a useful for private projects + +**Maintained by:** Thomas Gazagnaire (@samoht, Tarides), Etienne Millon (@emillon, Tarides), Marek Kubica (@Leonidas-from-XIV, Tarides) + +### Opam-publish + +**Notable Activity** +- Integration of Opam CI Lint functionality into `opam-publish` ([#166](https://github.com/ocaml-opam/opam-publish/pull/166), [#165](https://github.com/ocaml-opam/opam-publish/issues/165)) to validate packages before submission +- A new `--pre-release` argument added to handle pre-release packages correctly ([#164](https://github.com/ocaml-opam/opam-publish/pull/164)) + +**Maintained by:** Raja Boujbel (@rjbou - OCamlPro), Kate Deplaix (@kit-ty-kate, Ahrefs) diff --git a/data/news/platform/platform-2025-04.md b/data/news/platform/platform-2025-04.md new file mode 100644 index 0000000000..0cda82187d --- /dev/null +++ b/data/news/platform/platform-2025-04.md @@ -0,0 +1,246 @@ +--- +title: "Platform Newsletter: February - April 2025" +description: Update from the OCaml Platform. +date: "2025-05-12" +tags: [platform] +--- + +Welcome to the fourteenth edition of the OCaml Platform newsletter! + +In this February to April 2025 edition, we are excited to bring you the latest on the OCaml Platform, continuing our tradition of highlighting recent developments as seen in [previous editions](https://discuss.ocaml.org/tag/platform-newsletter). To understand the direction we're headed, especially regarding development workflows and user experience improvements, check out our [roadmap](https://ocaml.org/docs/platform-roadmap). + +You can [comment on this newsletter on the OCaml Discuss Forums](https://discuss.ocaml.org/t/ocaml-platform-newsletter-february-to-april-2025/16644)! + +You can [subscribe to this newsletter on LinkedIn](https://www.linkedin.com/newsletters/ocaml-platform-newsletter-7305270694567661568/)! + +**Highlights:** +- **Dune Package Management is now Compatible with Large Parts of the Ecosystem**: The majority of Dune-based packages in opam-repository now build successfully with Dune package management. Continuous monitoring is available at [dune.check.ci.dev](https://dune.check.ci.dev). Technical barriers are being systematically addressed while maintaining compatibility with both opam and Dune workflows to ensure teams can transition at their own pace. +- **Odoc 3.0 Release**: A major upgrade, introducing powerful features like type-based search through Sherlodoc, global sidebar navigation, integrated source code display, multimedia support, hierarchical documentation pages, and cross-package linking that creates truly connected documentation. +- **New minor Emacs Mode:** OCaml-eglot replaces the venerable "merlin-mode", providing modern editor features through `ocaml-lsp-server`. +- **First alpha of opam 2.4.0**: Significant improvements including removal of GNU patch/diff dependencies, better Nix integration, improved pinned repository visibility, UI enhancements for deprecated packages, and new version comparison tools and lock file management features. + +**Announcements:** +* ["opam 2.4.0 alpha1 release" on the Opam Blog](https://opam.ocaml.org/blog/opam-2-4-0-alpha1/) +* [OCaml Infrastructure: FreeBSD 14.2 Upgrade](https://ocaml.org/changelog/2025-03-26-freebsd-14.2) +* [OCaml Infrastructure: OCaml-version 4.0.0 released](https://ocaml.org/changelog/2025-03-24-recent-ocaml-versions) + +**Calls for Feedback:** +* [Dune Developer Preview Adoption Survey](https://discuss.ocaml.org/t/ann-dune-developer-preview-updates/15160/57?u=sabine) +* [OCaml Editor Plugins Survey](https://discuss.ocaml.org/t/ocaml-editors-plugins-survey/16216) +* [Asking For Community Feedback on the OCaml Platform Communications](https://discuss.ocaml.org/t/asking-for-community-feedback-on-the-ocaml-platform-communications/16142) + +**Releases:** + +* [opam 2.4.0~alpha1](https://discuss.ocaml.org/t/ann-opam-2-4-0-alpha1/16520) +* [Dune 3.18.2](https://ocaml.org/changelog/2025-04-30-dune.3.18.2) +* [Dune 3.18.1](https://ocaml.org/changelog/2025-04-17-dune.3.18.1) +* [Dune 3.18.0](https://ocaml.org/changelog/2025-04-03-dune.3.18.0) +* [Odoc 3.0](https://ocaml.org/changelog/2025-03-20-odoc-3.0.0) +* [dune-release 2.1.0](https://ocaml.org/changelog/2025-02-03-dune-release-2.1.0) +* [Ppxlib 0.36.0](https://ocaml.org/changelog/2025-03-05-ppxlib-0.36.0) +* [Ppxlib 0.35.0](https://ocaml.org/changelog/2025-02-04-ppxlib-0.35.0) +* [ocaml-eglot 1.2.0](https://discuss.ocaml.org/t/ann-release-of-ocaml-eglot-1-2-0/16515) +* [ocaml-eglot 1.1.0](https://github.com/tarides/ocaml-eglot/releases/tag/1.1.0) + +## **Dune** + +**Roadmap:** [Develop / (W4) Build a Project](https://ocaml.org/docs/platform-roadmap#w4-build-a-project) + +Dune 3.18 brings various quality-of-life improvements, bug fixes, and new features. It introduces support for the new `x-maintenance-intent` field in opam packages, allowing maintainers to better communicate project status. The release also includes the new `(format-dune-file ...)` stanza, formalizing the dune format-dune-file command as an inside rule, and adds support for the `not` operator in package dependencies constraints. Several improvements to cache handling of file permissions have been implemented, and users can now utilize the `--prefix` flag when configuring dune with `ocaml configure.ml`, providing greater installation flexibility. + +From 3.18.0, Dune now uses shorter paths for inline-test artifacts, allows dash characters in project names created with `dune init`, and displays negative error codes on Windows in hexadecimal format — the customary way to display `NTSTATUS` codes. The release also enhances stability with improved retry mechanisms for file delete operations on Windows under heavy load and provides better warning behavior when failing to discover the project root due to read failures, replacing the previous abort behavior. + +Shortly after, Dune 3.18.1 was released with a hotfix that corrects an issue where `pkg-config` would fail to find certain libraries in specific contexts, while Dune 3.18.2 provides support for the upcoming OCaml 5.4 release. + +**Activities:** +* [Release of Dune 3.18.2](https://ocaml.org/changelog/2025-04-30-dune.3.18.2) +* [Release of Dune 3.18.1](https://ocaml.org/changelog/2025-04-17-dune.3.18.1) +* [Release of Dune 3.18.0](https://ocaml.org/changelog/2025-04-03-dune.3.18.0) + +**Maintained by:** Rudi Grinberg (@rgrinberg, Jane Street), Nicolás Ojeda Bär (@nojb, LexiFi), Marek Kubica (@Leonidas-from-XIV, Tarides), Ali Caglayan (@Alizter), Etienne Millon (@emillon, Tarides), Stephen Sherratt (@gridbugs, Tarides), Antonio Nuno Monteiro (@anmonteiro), Etienne Marais (@maiste) + +### **Dune Package Management** + +As of May 9, a large part of Dune-based packages on `opam-repository` now build successfully with Dune package management. At [dune.check.ci.dev](https://dune.check.ci.dev), we provide continuous monitoring of build success across the ecosystem, giving visibility into compatibility before migration. + +The effort of making Dune package management compatible with the wider OCaml ecosystem is ongoing and aims to assess when Dune package management is ready for adoption in production settings. We are committed to maintain compatibility with both opam and Dune workflows, ensuring teams can transition at their own pace with minimal disruption to existing projects + +Technical barriers have been and are being systematically addressed, e.g. improved handling of ZIP archives, better dependency conflict resolution, and enhanced support for pinned packages that don't use Dune's build system. + +**Activities:** +* ["Expanding Dune Package Management to the Rest of the Ecosystem" on the Tarides Blog](https://tarides.com/blog/2025-04-11-expanding-dune-package-management-to-the-rest-of-the-ecosystem/) + +### **Dune Developer Preview** + +[Dune Developer Preview](https://preview.dune.build/) is an experimental channel that introduces cutting-edge features to streamline OCaml development workflows. Building upon Dune's foundation as OCaml's official build system, this initiative allows us to iterate quickly on ideas and experiment with improving the developer experience and with experimental features. For example, one feature that came out of Dune Developer Preview and made it into the upstream codebase is package management: by enabling Dune to deal with project dependencies, we eliminate the need to juggle multiple tools. + +The tooling includes built-in LSP support, formatting capabilities, and a shared cache that dramatically improves build performance. Early adopters are encouraged to [provide feedback](https://docs.google.com/forms/u/2/d/e/1FAIpQLSda-mOTHIdATTt_e9dFmNgUCy-fD55Qzr3bGGsxpfY_Ecfyxw/viewform?usp=send_form) as these experimental features mature toward stable releases. + +We are in the process of adopting Dune Developer Preview for the OCaml Platform Tools and other projects. This is to ensure that (1) Dune Developer Preview keeps providing a good developer experience on production codebases and (2) to catch bugs and issues as early as we can. At the moment, we are making a concerted effort to fix issues and add necessary features that block adoption of Dune Developer Preview on the OCaml Platform Tools projects. + +We're always interested in and addressing community feedback and bug reports, as well. In March, we conducted a [public survey to better understand the reach, adoption, and experience of/with Dune Developer Preview](https://discuss.ocaml.org/t/ann-dune-developer-preview-updates/15160/57) in the OCaml community. + +**Activities:** +* [Dune Developer Preview Adoption Survey](https://discuss.ocaml.org/t/ann-dune-developer-preview-updates/15160/57?u=sabine) + +## **Editor Tools** + +**Roadmap:** [Edit / (W19) Navigate Code](https://ocaml.org/tools/platform-roadmap#w19-navigate-code), [Edit / (W20) Refactor Code](https://ocaml.org/tools/platform-roadmap#w20-refactor-code) + +To better understand how the OCaml community uses the different editor plugins available for OCaml, and to get an idea which features are most anticipated, we ran a [survey on the OCaml Editors Plugins](https://discuss.ocaml.org/t/ocaml-editors-plugins-survey/16216). + +**Notable Activity** +* [OCaml Editor Plugins Survey](https://discuss.ocaml.org/t/ocaml-editors-plugins-survey/16216) +* [April 2025 Editors Dev Meeting](https://github.com/ocaml/merlin/wiki/Public-dev%E2%80%90meetings#-ulysse-voodoos--xavier-xvw--pizzie-piziedust--sonja-pitag-ha--florian-angeletti-octachron--darius-foo-dariusf--andrey-popp-andreypopp--nicolas-ojeda-b%C3%A4r-nojb) + Focus: Project-wide occurrences demo +* [February 2025 Editors Dev Meeting](https://github.com/ocaml/merlin/wiki/Public-dev%E2%80%90meetings#-pixie-dust--x-gerard-vemeulen--x-jack-joergensen--x-jean-marc-eber--x-arthur-wendling--x-xavier-van-de-woestyne--x-nicolas-ojeda-bar--x-ulysee-gerard--x-joy-odinaka) + Focus: Introduction of ocaml-eglot Emacs mode + +**OCaml LSP Server maintained by:** Ulysse Gérard (@voodoos, Tarides), Xavier Van de Woestyne (@xvw, Tarides), Rudi Grinberg (@rgrinberg, Jane Street) + +**Merlin maintained by:** Ulysse Gérard (@voodoos, Tarides), Xavier Van de Woestyne (@xvw, Tarides) + +### Merlin and OCaml LSP Server + +Project-wide occurrences are available in both Merlin and OCaml-LSP, allowing developers to find all instances of a symbol across their codebase by running `dune build @build-index -w`. The feature has basic editor support via `merlin-project-occurrences` in Emacs and `:MerlinOccurrencesProjectWide` in Vim. Additionally, users of OCaml 5.3 and LSP-based plugins can experiment with the first iteration on project-wide *renaming*. + +### Visual Studio Code plugin + +Behind the scenes, some work is happening on improving the developer experience for the OCaml VSCode editor plugin: When `ocaml-lsp-server` is not found in the opam switch, the plugin will prompt the user to offer installing it, and we are working on making the editor plugin work seamlessly with the recent dune package management features. + +**Notable Activity** + +- WIP on opam: Automatically installing/updating ocaml-lsp-server https://github.com/ocamllabs/vscode-ocaml-platform/pull/1725 +- WIP on Dune: Automatically configuring dune package management: https://github.com/ocamllabs/vscode-ocaml-platform/pull/1791 + + +### Emacs support + +On January 17, [OCaml-eglot version 1.0.0 was released](https://discuss.ocaml.org/t/ann-release-of-ocaml-eglot-1-0-0/15978/14), providing a new +minor emacs mode to enable the editor features provided by **ocaml-lsp-server**. +This replaces the venerable “merlin-mode”, after many years of loyal service. + +Subsequent releases [`1.1.0`](https://github.com/tarides/ocaml-eglot/releases/tag/1.1.0) and [`1.2.0`](https://discuss.ocaml.org/t/ann-release-of-ocaml-eglot-1-2-0/16515) enable support for +`flycheck` as a configurable alternative to `flymake` (`1.0.0` release), +Emacs `30.1` support, better user experience and error handling, as +well as support for new features. + +All these features have enabled OCaml-eglot to support client commands, making it possible to extend OCaml-eglot more easily and to integrate features much more rapidly. Since version `1.2.0`, OCaml-eglot has all the functions of Merlin mode (and more)! + +We encourage you to try `ocaml-eglot` (refer to the updated [documentation on editor setup on OCaml.org](https://ocaml.org/docs/set-up-editor#emacs)) and to [give feedback / report bugs by raising an issue on the ocaml-eglot repository](https://github.com/tarides/ocaml-eglot/issues)! + +Besides this, we have updated the documentation on Editor Setup on OCaml.org to reflect the new situation for Emacs! + +**Notable Activity** +- [Updated Tutorial on Setting Up Emacs Support on OCaml.org](https://ocaml.org/docs/set-up-editor#emacs) +- [Release of ocaml-eglot 1.1.0](https://github.com/tarides/ocaml-eglot/releases/tag/1.1.0) +- [Release of ocaml-eglot 1.2.0](https://discuss.ocaml.org/t/ann-release-of-ocaml-eglot-1-2-0/16515) + +## **Documentation Tools** + +**Roadmap:** [Share / (W25) Generate Documentation](https://ocaml.org/tools/platform-roadmap#w25-generate-documentation) + +### Odoc + +Odoc 3.0 has arrived after more than a year of development since the previous 2.4 release, bringing significant enhancements to OCaml's documentation tooling. The update introduces powerful new features including type-based search functionality through [Sherlodoc](https://github.com/ocaml/odoc/tree/master/sherlodoc), a global sidebar for improved navigation across documentation pages, and integrated source code display that allows developers to jump directly from documentation to rendered source regardless of module system complexity. Additional highlights include support for multimedia content (images, video, and audio), hierarchical documentation pages for better structure, and cross-package linking capabilities that create truly connected documentation, as well as support for incremental documentation builds. + +It's worth noting that Dune does not yet support Odoc 3 as its rules need rewriting to accommodate the new CLI and incremental build capabilities. In the interim, developers can use the standalone `odoc_driver` command to generate documentation for their packages as shown in the ["Remapping dependencies" documentation](https://ocaml.github.io/odoc/odoc-driver/index.html#remapping-dependencies). + +The Odoc team encourages all OCaml developers to test their documentation with the new release before publishing packages, which can help avoid post-release fixes like [this example](https://github.com/ocaml/odoc/pull/1333). For a practical introduction to the new features, developers can install the package via `opam install odoc-driver` and explore the comprehensive documentation available for the [Odoc toolchain](https://ocaml.github.io/odoc/). + +**Notable Activity** +- [Release of odoc 3.0.0](https://ocaml.org/changelog/2025-03-20-odoc-3.0.0) +- ["Odoc 3: So what?" on Jon Ludlam's blog](https://jon.recoil.org/blog/2025/04/odoc-3.html) - blog post that touches on how odoc 3's cross-package linking capabilities enable writing better manuals + +**Maintained by:** Jon Ludlam (@jonludlam, Tarides), Daniel Bünzli (@dbuenzli), Jules Aguillon (@julow, Tarides), Paul-Elliot Anglès d'Auriac (@panglesd, Tarides), Emile Trotignon (@EmileTrotignon, Tarides, then Ahrefs) + +## **Package Management** + +### Opam + +The [first alpha of opam 2.4.0 has been released](https://opam.ocaml.org/blog/opam-2-4-0-alpha1/), bringing significant improvements. + +The removal of GNU `patch` and `diff` as runtime dependencies reduces cross-platform inconsistencies, as the manager now uses the native OCaml `patch` library instead. Nix users will appreciate Nix support for external dependencies, facilitating more consistent environments across development and production systems. + +Notable for daily development work: pinned VCS repositories now display their current revision for better traceability, and several UI improvements provide clearer visibility into deprecated packages. The enhanced command set includes version comparison tools and better lock file management with `opam lock --keep-local`, particularly useful for maintaining consistent dependency states across team environments. + +Teams running NixOS will benefit from fixed sandboxing support, while the new `OPAMSOLVERTOLERANCE` environment variable helps resolve persistent solver timeouts that previously was unsolvable by MCCS. + +Early testing and feedback from development teams is encouraged to ensure a stable final release. Please [report any issues to the bug-tracker](https://github.com/ocaml/opam/issues). + +**Notable Activity** +- ["opam 2.4.0 alpha1 release" on the Opam Blog](https://opam.ocaml.org/blog/opam-2-4-0-alpha1/) +- `opam upgrade` fixes [#6373](https://github.com/ocaml/opam/pull/6373) +- Use `patch` OCaml library instead of the `patch` command [#5892](https://github.com/ocaml/opam/pull/5892) +- Add some lints [#6317](https://github.com/ocaml/opam/pull/6317), [#6438](https://github.com/ocaml/opam/pull/6438) +- Pinning system fixes [#5471](https://github.com/ocaml/opam/pull/5471), [#6343](https://github.com/ocaml/opam/pull/6343), [#6309](https://github.com/ocaml/opam/pull/6309), [#6375](https://github.com/ocaml/opam/pull/6375), [#6256](https://github.com/ocaml/opam/pull/6256), [#5471](https://github.com/ocaml/opam/pull/5471) +- Add `opam admin migrate-extrafiles` command [#5960](https://github.com/ocaml/opam/pull/5960), change opam admin check options [#6335](https://github.com/ocaml/opam/pull/6335) +- Depext system: better performance [#6324](https://github.com/ocaml/opam/pull/6324), enhance OpenBSD [#6362](https://github.com/ocaml/opam/pull/6362) +- Some UI improvments [#6376](https://github.com/ocaml/opam/pull/6376), [#6401](https://github.com/ocaml/opam/pull/6401), [#6358](https://github.com/ocaml/opam/pull/6358), [#6273](https://github.com/ocaml/opam/pull/6273) +- UX improvments: remove `ocaml-system` from default compiler at init [#6307](https://github.com/ocaml/opam/pull/6307) +- Provide a way to avoid solver timeouts [#5510](https://github.com/ocaml/opam/pull/5510) +- Add `opam lock --keep-local` [#6411](https://github.com/ocaml/opam/pull/6411) + +**Maintained by:** Raja Boujbel (@rjbou - OCamlPro), Kate Deplaix (@kit-ty-kate, Ahrefs), David Allsopp (@dra27, Tarides) + +### Dune-release + +**Roadmap:** [Share / (W26) Package Publication](https://ocaml.org/tools/platform-roadmap#w26-package-publication) + +Dune-release 2.1.0, has been released, providing a new command `dune-release delegate-info version`, which makes it easier to identify the current version of a package as inferred by the tool. Additionally, the release introduces more flexibility with the `--dev-repo` flag for `dune-release` and `dune-release publish` commands, allowing users to override the `dev-repo` field specified in the `.opam` file during the release process. + +Dune-release no longer publishes documentation to GitHub Pages by default. This decision reflects the OCaml ecosystem's consolidation around centralized documentation, as package documentation is now automatically built and served by [ocaml.org/packages](https://ocaml.org/packages) following publication to the opam repository. + +The update also improves compatibility and resolves several issues, including a fix for decoding GitHub URLs and ensuring dune-release works with the experimental package management feature from Dune. The tool now handles the presence of `~/.dune/bin/dune` without failing, making it more robust for developers exploring Dune's newer features. + +**Notable Activity** +* [Release of dune-release 2.1.0](https://ocaml.org/changelog/2025-02-03-dune-release-2.1.0) + +**Maintained by:** Thomas Gazagnaire (@samoht, Tarides), Etienne Millon (@emillon, Tarides), Marek Kubica (@Leonidas-from-XIV, Tarides) + +## Ppxlib + +The ppxlib team has released versions 0.35.0 and 0.36.0! + +Ppxlib 0.35.0, released in February 2025, brings significant improvements for OCaml 5.3 compatibility by allowing ppx rewriters to operate on files containing the new effect syntax. While ppx extensions and effect syntax can coexist, developers should note that rewriters might encounter errors when processing effect syntax nodes in extension payloads or generated code. The release introduces a new `--use-compiler-pp` driver flag, useful for preserving effect syntax when outputting source code instead of marshalled AST. This update also removes support for compilers older than 4.08. + +The latest ppxlib 0.36.0, released in March 2025, updates the internal AST to target OCaml 5.2, enabling ppx authors to leverage features from this version while maintaining compatibility with OCaml 4.08.0 and newer. This release includes notable changes to the representation of functions. Thus, package authors are strongly encouraged to consult [the upgrade guide](https://github.com/ocaml-ppx/ppxlib/wiki/Upgrading-to-ppxlib-0.36.0) as many ppxes may break. + +Other improvements include fixing a bug in `loc_of_attribute`, adding support for the `[@@@expand_inline]` transformation and floating attribute context-free transformations, and introducing a `-raise-embedded-errors` flag to the driver. + +**Notable Activity** +* [Release of ppxlib 0.36.0](https://ocaml.org/changelog/2025-03-05-ppxlib-0.36.0) +* [Release of ppxlib 0.35.0](https://ocaml.org/changelog/2025-02-04-ppxlib-0.35.0) +* [Upgrade guide for the OCaml 5.3 release of ppxlib](https://github.com/ocaml-ppx/ppxlib/wiki/Upgrading-to-ppxlib-0.36.0) + +**Maintained by:** Patrick Ferris ([@patricoferris](https://github.com/patricoferris)) + +## OCaml Infrastructure + +The OCaml infrastructure team has upgraded their OBuilder workers for FreeBSD from version 14.1 to 14.2, which directly impacts two key continuous integration services: + +1. **OCaml-CI** ([ocaml.ci.dev](https://ocaml.ci.dev)) - This service automatically tests OCaml projects hosted on GitHub, and will now test against FreeBSD 14.2 instead of 14.1. Projects using this CI service will automatically be tested against the newer FreeBSD version. +2. **opam-repo-CI** ([opam.ci.ocaml.org](https://opam.ci.ocaml.org)) - This service tests pull requests to the opam package repository, and will also now test against FreeBSD 14.2 rather than 14.1. + +With the release of `ocaml-version` 4.0.0, the OCaml version considered "recent" has been raised from 4.02 to 4.08. This change affects multiple services that use this definition to determine which OCaml versions to test against: + +1. **OCaml-CI** - Will adjust which OCaml compiler versions are tested by default for projects +2. **opam-repo-CI** - Will modify its testing matrix for packages in the opam repository +3. **Docker base image builder** - Will only build images for OCaml 4.08 and newer + +As these services update, testing on older OCaml releases (versions 4.02 through 4.07) will be gradually removed. Package maintainers should consider upgrading projects still using pre-4.08 OCaml versions to OCaml 4.08 or higher. + +Apart from this, at the end of April 2025, registry.ci.dev, opam-repo-ci, OCaml-CI and get.dune.build were moved from Equinix Hosting to hosting at the Cambridge University Computer Lab, because of the [sunset of the Equinix Metal platform](https://deploy.equinix.com/blog/sunsetting-equinix-metal/). + +**Notable Activity** +* ["Moving OCaml-CI" on tunbury.org](https://www.tunbury.org/ocaml-ci/) +* ["Equinix Moves" on tunbury.org](https://www.tunbury.org/equinix-moves/) +* [OCaml Infrastructure: FreeBSD 14.2 Upgrade](https://ocaml.org/changelog/2025-03-26-freebsd-14.2) +* [OCaml Infrastructure: OCaml-version 4.0.0 released](https://ocaml.org/changelog/2025-03-24-recent-ocaml-versions) + +### WIP: Odoc 3 on OCaml-Docs-CI + +The OCaml documentation pages provided through the [OCaml.org package area](https://ocaml.org/packages) are scheduled to receive significant updates with the release of odoc 3. To enable odoc 3 and all of its new features on OCaml.org, we are overhauling the docs-ci pipeline that powers documentation on ocaml.org. The improved pipeline addresses dependency complexities by using a new tool (https://github.com/jonludlam/opamh) that archives and restores opam packages, eliminating redundant builds of packages like dune that previously occurred thousands of times. The underlying infrastructure is also being upgraded, with plans to migrate docs-ci to a new blade server. + +**Notable Activity** +* ["OCaml-Docs-CI and Odoc 3" on Jon Ludlam's blog](https://jon.recoil.org/blog/2025/04/ocaml-docs-ci-and-odoc-3.html) diff --git a/data/outreachy.yml b/data/outreachy.yml index 5d29b5518f..621b45570f 100644 --- a/data/outreachy.yml +++ b/data/outreachy.yml @@ -456,4 +456,38 @@ rounds: - Paul-Elliot Anglès d'Auriac - Jules Aguillon video: https://watch.ocaml.org/w/peT3MdWjS1BYYMbowEJ1gv?start=3m07s + - name: December 2024 + projects: + - title: Structural Diffing Algorithm for OCaml Libraries API + description: > + OCaml is a functional programming language. As with most languages, users + eventually package bits of their code into libraries so that others may also + benefit from their work. Those libraries evolve through time and multiple + versions are released along the way, each with its own set of changes. Some + changes are transparent to the library users, such as bug fixes that improve + a faulty behaviour. Some others modify the interface of the library: its API, + i.e. the set of types, values and functions it provides, sometimes requiring + its users to change parts of their code to adapt. + + As libraries grow in size and complexity, it can become difficult for + maintainers to keep track of how a change in their codebase impacts the public + API. + [ocaml-api-watch](https://github.com/NathanReb/ocaml-api-watch) is a fresh + project that aims at providing a suite of tools to help OCaml library + maintainers and users deal with changes in the public API of their libraries or + the ones they use. This includes tools to detect potentially unwanted breaking + changes before releasing a new version or to determine the version of a library + that introduced a new function. + + The first prototype of the api diffing tool was completed during the previous + outreachy round. + The goal of the internship this time will be to extend the prototype to support + a wider part of the OCaml interface representation and to implement a proper + structural diffing algorithm. + mentee: "Abdulaziz Alkurd" + source: https://github.com/ocaml-semver/ocaml-api-watch + mentors: + - Nathan Rebours + - Paul-Elliot + video: https://watch.ocaml.org/w/eWRikkpwoox1SboAwrDshD diff --git a/data/pages/code_of_conduct.md b/data/pages/code_of_conduct.md index 9050659707..173bf7dfd2 100644 --- a/data/pages/code_of_conduct.md +++ b/data/pages/code_of_conduct.md @@ -110,7 +110,7 @@ The members of the team are currently: * Marcello Seri <[marcello@ocaml.org](mailto:marcello@ocaml.org)> * Raja Boujbel <[raja@ocaml.org](mailto:raja@ocaml.org)> * Simon Cruanes <[simon@ocaml.org](mailto:simon@ocaml.org)> -* Sonja Heinze <[sonja@ocaml.org](mailto:sonja@ocaml.org)> +* Shon Feder <[shon@ocaml.org](mailto:shon@ocaml.org)> ## Strained Situations ## diff --git a/data/planet-sources.yml b/data/planet-sources.yml index b6977f300a..fdbccf61f4 100644 --- a/data/planet-sources.yml +++ b/data/planet-sources.yml @@ -194,3 +194,6 @@ name: Debajyati's Blog url: https://debajyatidey.hashnode.dev/rss.xml only_ocaml: true +- id: bbatsov + name: Bozhidar Batsov + url: https://batsov.com/feeds/OCaml.xml diff --git a/data/planet/-individual_external_links/undo-monad.md b/data/planet/-individual_external_links/undo-monad.md new file mode 100644 index 0000000000..2355f692e5 --- /dev/null +++ b/data/planet/-individual_external_links/undo-monad.md @@ -0,0 +1,11 @@ +--- +title: "How I fixed Slipshow's worst flaw using OCaml and a monad" +description: "Rewriting the Slipshow engine from JavaScript to OCaml allowed me to fix an embarassing set of bugs, in an elegant way. This is the story of it!" +url: https://choum.net/panglesd/undo-monad/ +date: 2025-02-21T08:00:00-00:00 +authors: + - Paul-Elliot Anglès d'Auriac +source: + name: "panglesd on his personal website" + url: https://choum.net/panglesd +--- diff --git a/data/planet/ahrefs/openai-and-structured-outputs-from-ocaml.md b/data/planet/ahrefs/openai-and-structured-outputs-from-ocaml.md new file mode 100644 index 0000000000..3e97ff712b --- /dev/null +++ b/data/planet/ahrefs/openai-and-structured-outputs-from-ocaml.md @@ -0,0 +1,12 @@ +--- +title: OpenAI and structured outputs from OCaml +description: with magic, without (touching) JSON +url: https://tech.ahrefs.com/openai-and-structured-outputs-from-ocaml-b198fcf701ca?source=rss----303662d88bae--ocaml +date: 2025-03-07T14:00:13-00:00 +preview_image: https://miro.medium.com/v2/resize:fit:1200/1*fqTZQ1N1O61fct-kRKAXSA.jpeg +authors: +- Ahrefs +source: +--- + +

What makes this approach special?

OpenAI offers a way to have (relatively) typed communication through structured outputs. A json schema must be passed alongside the prompt. And the answer is guaranteed to follow that schema.

When working with OpenAI’s structured outputs, you typically need to:

  1. Define your data structures
  2. Create a JSON schema that describes these structures
  3. Parse the API responses back into your data structures

This usually involves writing and maintaining JSON schemas by hand, which can be error-prone and tedious. The approach we’ll explore in this project eliminates this manual work by:

  • Using ppx_deriving_jsonschema to automatically generate JSON schemas from OCaml types
  • Combining it with ppx_yojson_conv to handle JSON serialization/deserialization
  • Creating a type-safe pipeline from OCaml types to OpenAI API and back

This means you can define your data model once in OCaml and get both the schema for OpenAI and the parsing logic for free!

Setting up the OpenAI client

The bindings to the API are kept fairly minimal in this example. We are using Devkit for the http client. And ppx_yojson_conv to conveniently emit/parse the necessary json.

open Ppx_yojson_conv_lib.Yojson_conv.Primitives

let api_key = Sys.getenv "OPENAI_API_KEY"

module OpenAI = struct
let model = "gpt-4o"

type json = Yojson.Safe.t
let yojson_of_json x = x

module Response = struct
type response_message = { content : string option }
[@@deriving of_yojson] [@@yojson.allow_extra_fields]

type choice = { message : response_message }
[@@deriving of_yojson] [@@yojson.allow_extra_fields]

type response = { choices : choice list }
[@@deriving of_yojson] [@@yojson.allow_extra_fields]
end

module Request = struct
type message = {
role : string;
content : string;
}
[@@deriving yojson_of]

type json_schema = {
name : string;
schema : json;
}
[@@deriving yojson_of]

type response_format = {
typ : string; [@key "type"]
json_schema : json_schema;
}
[@@deriving yojson_of]

type request = {
model : string;
messages : message list;
response_format : response_format;
}
[@@deriving yojson_of]
end

let send ?(debug = false) request =
let body = `Raw ("application/json", request |> Request.yojson_of_request |> Yojson.Safe.to_string) in
let () =
if debug then (
let (`Raw (_, body)) = body in
Printf.eprintf "Body: %s\n" body)
in
let headers = [ "Authorization: Bearer " ^ api_key ] in
match Devkit.Web.http_request ~headers ~body `POST "https://api.openai.com/v1/chat/completions" with
| `Error e -> Error e
| `Ok response ->
try Ok (response |> Yojson.Safe.from_string |> Response.response_of_yojson)
with exn -> Error (Printf.sprintf "error while parsing the response %s: %S" (Printexc.to_string exn) response)
end

The types defined in the Request and Response modules are straight translation of the OpenAI API reference. The [@@deriving of_yojson] annotation generates functions to convert JSON from/into these types. The [@@yojson.allow_extra_fields] attribute ensures our code won't break if OpenAI adds new fields to their API responses.

The send function is a thin wrapper around the HTTP request to OpenAI's API, serializing our request to JSON, sending it, and then parsing the response back into our OCaml types.

Notice how we’re using PPX extensions throughout this code to minimize boilerplate. Without these extensions, we would already need to write a lot of manual serialization and deserialization code.

Creating a structured schema for math problem solving

In this example, I will demonstrate how to use OpenAI as a math tutor to solve problems with step-by-step details. Instead of receiving a single block of text that would require parsing to extract individual steps, I’ll define a structured JSON schema. The schema requires each step to include both an explanation and an intermediate output, along with a final answer.

Here’s where the magic of ppx_deriving_jsonschema comes in:

module Math_reasoning = struct
type step = {
explanation : string;
output : int;
}
[@@deriving jsonschema, yojson]

type math_reasoning = {
steps : step list;
final_answer : int;
}
[@@deriving jsonschema, yojson] [@@yojson.allow_extra_fields]
end

Let’s break down what’s happening here:

  1. We define OCaml types that model our desired response structure
  2. The [@@deriving jsonschema] annotation automatically generates a JSON schema value called TYPENAME_jsonschema for each type
  3. The [@@deriving yojson] annotation generates functions to convert between our OCaml types and JSON
  4. These PPX extensions work together seamlessly — the schema generated by jsonschema is compatible with the JSON handling from yojson

Without these PPX extensions, we would need to:

  • Manually write a JSON schema as a string or build it with yojson
  • Write custom code to parse the API responses into our OCaml types
  • Ensure the schema and parsing logic stay in sync when our types change

Instead, we get all of this automatically from a single type definition!

Using the schema in our OpenAI request

Once our schema is ready, it is easy to insert it in the request, alongside with the prompt.

let math_tutor_request user_prompt =
{
OpenAI.Request.model = OpenAI.model;
messages =
[
{
role = "system";
content =
"You are a helpful math tutor. You will be provided with a math \
problem, and your goal will be to output a step by step solution, \
along with a final answer. For each step, just provide the output \
as an equation and use the explanation field to detail the \
reasoning.";
};
{ role = "user"; content = user_prompt };
];
response_format =
{
typ = "json_schema";
json_schema =
{
name = "math_reasoning";
schema = Math_reasoning.math_reasoning_jsonschema;
};
};
}

Processing the structured response

The remaining task is to retrieve the steps and display them. OpenAI has the ability to return multiple versions of its answer, calling it choices. Here we will only process one choice for simplicity.

let extract_steps { OpenAI.Response.message = { content }; _ } =
match content with
| None -> ()
| Some content ->
match content |> Yojson.Safe.from_string |> Math_reasoning.math_reasoning_of_yojson with
| exception Ppx_yojson_conv_lib.Yojson_conv.Of_yojson_error (exn, json) ->
Printf.eprintf "unable to parse response, error %s: %s\n" (Printexc.to_string exn) (Yojson.Safe.to_string json)
| { Math_reasoning.steps; final_answer } ->
List.iteri
(fun i { Math_reasoning.explanation; output } ->
Printf.printf "Step %d: %s\n" i explanation;
Printf.printf "Output: %f\n" output)
steps;
Printf.printf "Final answer: %f\n" final_answer

Notice how we’re using the math_reasoning_of_yojson function that was automatically generated by the [@@deriving yojson] annotation. Once we have the properly typed OCaml value, we can safely access its fields and process the steps in a type-safe manner. This is much more robust than manually parsing the JSON or using string manipulation to extract the information.

Putting it all together

Finally we only have to do a little bit of plumbing to make the program work. We get the question of the user from the command line, query the OpenAI API, and display the response.

let run user_prompt =
let request = math_tutor_request user_prompt in
match OpenAI.send request with
| Error e -> Printf.eprintf "error: %s\n" e
| Ok { OpenAI.Response.choices = []; _ } -> Printf.eprintf "no choices returned by OpenAI\n"
| Ok { OpenAI.Response.choices; _ } -> List.iter extract_steps choices

let () =
let user_prompt = Sys.argv.(1) in
run user_prompt

The output should look like this:

$ dune exec ./openai_demo.exe "compute 3+4*17-4/5"
Step 0: First, follow the order of operations, known as PEMDAS (Parentheses, Exponents, Multiplication and Division (from left to right), Addition and Subtraction (from left to right)). Start by handling the multiplication: Calculate 4 * 17 = 68.
Output: 68.000000
Step 1: Next, handle the division: Calculate 4 / 5 = 0.8.
Output: 0.800000
Step 2: Now, handle the addition to and subtraction from the result of the multiplication: Calculate 3 + 68 = 71.
Output: 70.200000
Step 3: Lastly, subtract the result of the division from the addition result: Calculate 71 - 0.8 = 70.2.
Output: 70.200000
Final answer: 70.200000

As you can see, the output of some of the steps is not correct. This is expected when performing mathematical operations using an LLM. Please always review the output with care.

The whole project can be found at https://github.com/ahrefs/ocaml-openai-demo.

The dependencies of the project can be installed from opam:

opam switch create . 5.3.0
opam install dune devkit ppx_yojson_conv ppx_yojson_conv_lib ppx_deriving_jsonschema

OpenAI and structured outputs from OCaml was originally published in Ahrefs on Medium, where people are continuing the conversation by highlighting and responding to this story.

diff --git a/data/planet/bbatsov/how-are-ocaml-programmers-called.md b/data/planet/bbatsov/how-are-ocaml-programmers-called.md new file mode 100644 index 0000000000..3542cd26fd --- /dev/null +++ b/data/planet/bbatsov/how-are-ocaml-programmers-called.md @@ -0,0 +1,46 @@ +--- +title: How are OCaml Programmers Called? +description: Ruby programmers are commonly called Rubyists. Python programmers are + often called Pythonistas. Lisp programmers are widely known as Lispers. Clojure + programmers are sometimes called Clojurians. +url: https://batsov.com/articles/2023/03/20/how-are-ocaml-programmers-called/ +date: 2023-03-20T08:02:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

Ruby programmers are commonly called Rubyists. Python programmers +are often called Pythonistas. Lisp programmers are widely known +as Lispers. Clojure programmers are sometimes called Clojurians.

+ +

Of course, in a lot more programming language communities such nicknames never +became common - e.g. Java, .NET, PHP and JavaScript.1 I wonder if those playful +nicknames are also a reflection of the spirit of a community or they are just a +side-effect of how easy it’s to derive something from the name a programming +language.

+ +

But what about OCaml programmers? (O)Camlers? (O)Camlists? (O)Camlians? (O)Camlurians? Caml Riders?

+ +

I’ve been wondering about this in the background of my mind ever +since I got interested in OCaml last year. I finally decided to do +a bit of digging around and I’ve discovered that there’s no popular/common +term for OCaml programmers. The members of the community did +have some cool ideas, though.

+ +
+

Since we stealthy move between pure and impure environments, Cameleons seems appropriate.

+
+ +

Indeed! I like this one a lot, as I think it captures perfectly OCaml’s creed. So, let them be know as Cameleons going forward! Or Camleons? Naming is hard!

+ +

Oh, Camleons, that’s all I have for you today. Keep hacking and may your code always compile from the first try! And occasionally even do the thing you intended it to!

+ +
+
    +
  1. +

    At least in English. In Bulgaria we have nicknames for pretty much every type of programmer. E.g. if you’re Java programmer you’d often by called Javar or Javajiya. PHP programmers are PHPars. C programmers are See-ee-ji-ee. Not super original, but very versatile. 

    +
  2. +
+
diff --git a/data/planet/bbatsov/learning-ocaml-functions-without-parameters.md b/data/planet/bbatsov/learning-ocaml-functions-without-parameters.md new file mode 100644 index 0000000000..f59f3e2fdd --- /dev/null +++ b/data/planet/bbatsov/learning-ocaml-functions-without-parameters.md @@ -0,0 +1,79 @@ +--- +title: 'Learning OCaml: Functions without Parameters' +description: "A couple of days ago I noticed on OCaml\u2019s Discord server that someone + was confused by OCaml function applications (invocations) like these:" +url: https://batsov.com/articles/2025/03/02/learning-ocaml-functions-without-parameters/ +date: 2025-03-02T10:47:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

A couple of days ago I noticed on OCaml’s Discord server that someone was +confused by OCaml function applications (invocations) like these:

+ +
print_newline ()
+
+read_input ()
+
+ +

To people coming from “conventional” programming languages this might look like +calling a function/method without any arguments. (e.g. foo() in Python) Of course, +function application in OCaml is quite different from JavaScript, Python and the like - +the function arguments are space separated and simply follow the function’s name:

+ +
foo arg1 arg1 arg3
+
+ +

So what are those () then and why are they needed? I’ll start with the second part of the question. +In OCaml you can’t really define a function without any parameters - if we have to be super +precise, every function takes exactly one parameter, no matter how it might look +at a glance.1 If you try to do something like:

+ +
let my_print = print_endline "Hello"
+val my_print : unit = ()
+
+ +

You’ll just end up with static binding to nothing. Or not quite nothing, as it’s time to +talk about (), which happens to be the single instance of the unit type, used to represent +the absence of a meaningful value. So, when you want to define a function that doesn’t need +any parameters the convention is to use a single unit parameter:

+ +
(* This defines a function that takes unit *)
+let say_hello () =
+  print_endline "Hello, world!"
+
+(* same here *)
+let random_int () =
+  Random.int 100
+
+ +

I hope this also explains why’d have to call such functions with () as their +argument. If you don’t do this - you’d just receive the underlying function +object as the result:

+ +
# say_hello;;
+- : unit -> unit = <fun>
+# say_hello ();;
+Hello, world!
+- : unit = ()
+# random_int;;
+- : unit -> int = <fun>
+# random_int ();;
+- : int = 10
+
+ +

Basically, you need to pass the argument to have an actual function application. +Remember that in OCaml (and most functional programming languages), functions are first-class +objects that you can pass around like any other value.

+ +

And that’s a wrap. I hope you learned something useful today. Keep hacking!

+ + diff --git a/data/planet/bbatsov/learning-ocaml-matching-anything-or-the-lack-of-anything.md b/data/planet/bbatsov/learning-ocaml-matching-anything-or-the-lack-of-anything.md new file mode 100644 index 0000000000..fdebd6a90d --- /dev/null +++ b/data/planet/bbatsov/learning-ocaml-matching-anything-or-the-lack-of-anything.md @@ -0,0 +1,63 @@ +--- +title: 'Learning OCaml: Matching Anything or the Lack of Anything' +description: "I\u2019ve noticed that some newcomers to OCaml are a bit confused by + code like the following:" +url: https://batsov.com/articles/2025/02/27/learning-ocaml-matching-anything-or-the-lack-of-anything/ +date: 2025-02-27T11:48:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

I’ve noticed that some newcomers to OCaml are a bit confused by code like the following:

+ +
let () = print_endline "Hello, world"
+
+let _ = foo bar
+
+ +

Both of those are forms of pattern matching, but one of them is a lot stricter +than the other. In OCaml () is the single value of the unit type that +indicates the absence of any meaningful value. You can think of it as something like void in +other languages. What this means is that let () would only match an +expression that actually return unit (like the various print_* functions) and you’d get a compilation error +otherwise:

+ +
$ ocaml foo.ml
+File "./foo.ml", line 1, characters 9-11:
+1 | let () = 10
+             ^^
+Error: The constant 10 has type int but an expression was expected of type unit
+
+ +

_ on the other hand is a placeholder for “anything” and it will match… anything. It’s useful +in cases when you just need to discard something. A common example to illustrate it would be something +like pattern matching on the elements of a list. Consider the following trivial function that returns +the last item from a list:

+ +
let rec last = function
+  | [] -> None
+  | [x] -> Some x
+  | _ :: t -> last t
+
+ +

Just as in match, you can use let _ to match against any value, effectively discarding it.

+ +

In practice, let () is often used at the top level of programs to indicate the +main entry point, while let _ is used when you need to evaluate an expression +for its side effects but don’t care about its return value. I mostly use let _ when inserting +debug print expressions in a chain of nested lets. Here’s an example:

+ +
let foo x =
+  let _ = print_int x in
+  let y = x * 2 in
+  let _ = print_int y in
+  let z = y + 10 in
+  z
+
+ +

The above example is a bit contrived, but I hope you get the idea. Also, you can totally use let () in the example above, +although it seems to me that using let _ is more intention revealing in such cases.

+ +

That’s all I have for you today. Keep hacking!

diff --git a/data/planet/bbatsov/learning-ocaml-module-aliases.md b/data/planet/bbatsov/learning-ocaml-module-aliases.md new file mode 100644 index 0000000000..3ddccbfefb --- /dev/null +++ b/data/planet/bbatsov/learning-ocaml-module-aliases.md @@ -0,0 +1,60 @@ +--- +title: 'Learning OCaml: Module Aliases' +description: "OCaml is famous for allow you to do a lot of things like modules. Like + really a lot! Advanced features like functors, aside, it\u2019s really common to + either alias module names to something shorter or localize open Module_name to a + smaller scope:" +url: https://batsov.com/articles/2025/04/06/learning-ocaml-module-aliases/ +date: 2025-04-06T19:06:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

OCaml is famous for allow you to do a lot of things like modules. Like really a lot! +Advanced features like functors, aside, it’s really common to either alias +module names to something shorter or localize open Module_name to a smaller +scope:

+ +
(* module alias *)
+module Printf = P
+
+(* open module for subsequent scope *)
+let open Printf in
+let portfolio = List.map parse_line portfolio_lines in
+List.iter (fun (ticker, shares, price) ->
+  printf "%s: %d shares at $%.2f\n" ticker shares price
+) portfolio;
+let total = total_value portfolio in
+printf "Total portfolio value: $%.2f\n" total
+
+(* open module for an expression *)
+List.([1; 2; 3; 4; 5] |> map (fun x -> x * 2) |> fold_left (+) 0);;
+
+ +

All of them have their uses, but I’d like to also mention one less known +approach - namely a scoped module alias:

+ +
let module P = Printf in
+let portfolio = List.map parse_line portfolio_lines in
+List.iter (fun (ticker, shares, price) ->
+  P.printf "%s: %d shares at $%.2f\n" ticker shares price
+) portfolio;
+let total = total_value portfolio in
+P.printf "Total portfolio value: $%.2f\n" total
+
+ +

I think in some way that’s the best of both worlds as it makes it obvious +that certain functions are coming from a module, and you’re still not +doing that much extra typing. Finding the right balance between conciseness, +readability and maintainability is never easy, though.

+ +

Note: Interestingly OCaml’s younger sibling F# chose not to implement +scoped module opens at all. I’m guessing this happened due to maintainability +concerns.

+ +

What are your thoughts on the subject? In which situations would you prefer +let open Module in over a local module alias and vice versa?

+ +

That’s all I have for you today. Keep hacking!

diff --git a/data/planet/bbatsov/learning-ocaml-parsing-data-with-scanf.md b/data/planet/bbatsov/learning-ocaml-parsing-data-with-scanf.md new file mode 100644 index 0000000000..89b78a49ad --- /dev/null +++ b/data/planet/bbatsov/learning-ocaml-parsing-data-with-scanf.md @@ -0,0 +1,119 @@ +--- +title: 'Learning OCaml: Parsing Data with Scanf' +description: "In my previous article I mentioned that OCaml\u2019s Stdlib leaves a + lot to be desire when it comes to regular expressions. One thing I didn\u2019t discuss + back then was that the problem is somewhat mitigated by the excellent module Scanf, + which makes it easy to parse structured data." +url: https://batsov.com/articles/2025/04/06/learning-ocaml-parsing-data-with-scanf/ +date: 2025-04-06T08:40:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

In my previous article I mentioned that OCaml’s +Stdlib leaves a lot to be desire when it comes to regular +expressions. One thing I didn’t discuss back then was that +the problem is somewhat mitigated by the excellent module +Scanf, which makes it easy to parse structured data.

+ +

Image that we’re dealing with a simple investment portfolio, +where we have multiple records containing:

+ +
    +
  • Ticker symbol (e.g. AAPL)
  • +
  • Number of shares
  • +
  • Current share price
  • +
+ +

Let’s assume this portfolio is stored in .csv file and each +entry there looks something like APPL,10,150.50. While there +are many ways to parse this data, I think Scanf is probably +the simplest and most elegant of them:

+ +
Scanf.sscanf "AAPL, 10, 150.5" "%[^,], %d, %f" (fun ticker shares price -> (ticker, shares, price));;
+- : string * int * float = ("AAPL", 10, 150.5)
+
+ +

As you can see we’re using a parsing format specifier that’s pretty similar to what we’d +normally use with printf. %[^,] is kind of weird and it means “read string until ,”. +We can’t use the regular %s format specifier here, as it expects space-separated strings. +This, however, will work fine with %s:

+ +
Scanf.sscanf "John Doe 33" "%s %s %d" (fun name surname age -> (name, surname, age));;
+- : string * string * int = ("John", "Doe", 33)
+
+ +

Here’s a more complete example that parses a few portfolio records and +calculates the value of the portfolio:

+ +
(* Example portfolio entries as strings *)
+let portfolio_lines = [
+  "AAPL,10,178.23";
+  "GOOG,5,150.50";
+  "MSFT,20,299.01";
+]
+
+(* Parse a line into (ticker, shares, price) *)
+let parse_line line =
+  Scanf.sscanf line "%[^,],%d,%f" (fun ticker shares price ->
+    (ticker, shares, price)
+  )
+
+(* Compute total value of the portfolio *)
+let total_value entries =
+  List.fold_left (fun acc (_ticker, shares, price) ->
+    acc +. float_of_int shares *. price
+  ) 0.0 entries
+
+let () =
+  let open Printf in
+  let portfolio = List.map parse_line portfolio_lines in
+  List.iter (fun (ticker, shares, price) ->
+    printf "%s: %d shares at $%.2f\n" ticker shares price
+  ) portfolio;
+  let total = total_value portfolio in
+  printf "Total portfolio value: $%.2f\n" total
+
+ +

Not bad, right?

+ +

Scanf has several functions in it and quite a lot of format specifiers that you can +leverage in various situations.

+ +

The formatted input functions can read from any kind of input, including +strings, files, or anything that can return characters. The more general source +of characters is named a formatted input channel (or scanning buffer) and has +type Scanf.Scanning.in_channel. The more general formatted input function reads +from any scanning buffer and is named bscanf.

+ +

Generally speaking, the formatted input functions have 3 arguments:

+ +
    +
  • the first argument is a source of characters for the input,
  • +
  • the second argument is a format string that specifies the values to read,
  • +
  • the third argument is a receiver function that is applied to the values read.
  • +
+ +

My trivial examples dealt only with input strings, but you can easily leverage +other input sources. Here’s an example reading from the standard input:

+ +
Scanf.scanf "%s %f\n" (fun name price ->
+    Printf.printf "Item: %s, Price: %.2f\n" name price)
+
+(* input -> Table 100.20 *)
+
+(* output -> Item: Table, Price: 100.20 *)
+- : unit = ()
+
+ +

Enter something like “Chair 20.25” and observe the results.

+ +

I’d encourage everyone to get familiar with the module’s +documentation for all the nitty-gritty details.

+ +

Please, share in the comments how you’re using Scanf in your OCaml projects and any tips +you might have about making the best of it.

+ +

That’s all I have for you. Keep hacking!

diff --git a/data/planet/bbatsov/learning-ocaml-quoted-string-literals.md b/data/planet/bbatsov/learning-ocaml-quoted-string-literals.md new file mode 100644 index 0000000000..2e20accb73 --- /dev/null +++ b/data/planet/bbatsov/learning-ocaml-quoted-string-literals.md @@ -0,0 +1,150 @@ +--- +title: 'Learning OCaml: Quoted String Literals' +description: "While learning OCaml I\u2019ve noticed one curious feature - it has + two types of string literals. The first type are the common and quite familiar \u201Cdouble-quoted + string literals\u201D (or perhaps simply \u201Cstring literals\u201D?):" +url: https://batsov.com/articles/2023/04/20/learning-ocaml-quoted-string-literals/ +date: 2023-04-20T13:23:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

While learning OCaml I’ve noticed one curious feature - it has two +types of string literals. The first type are the common and quite +familiar “double-quoted string literals” (or perhaps simply “string literals”?):

+ +
let greeting = "Hello, World!\n"
+let superscript_plus = "\u{207A}";;
+val greeting : string = "Hello, World!\n"
+val superscript_plus : string = "⁺"
+
+ +

Nothing really surprising here, right? But then there are also what OCaml calls +quoted string +literals (a.k.a. “quoted strings”):

+ +
let quoted_greeting = {|"Hello, World!"|}
+let nested = {ext|hello {|world|}|ext};;
+val quoted_greeting : string = "\"Hello, World!\""
+val nested : string = "hello {|world|}"
+
+ +

Now that’s something you don’t see every day, right? Here’s how the official +manual describes them:

+ +
+

Quoted string literals provide an alternative lexical syntax for string +literals. They are useful to represent strings of arbitrary content without +escaping. Quoted strings are delimited by a matching pair of +{ quoted-string-id | and | quoted-string-id } with the same quoted-string-id on +both sides. Quoted strings do not interpret any character in a special way but +requires that the sequence | quoted-string-id } does not occur in the string +itself. The identifier quoted-string-id is a (possibly empty) sequence of +lowercase letters and underscores that can be freely chosen to avoid such +issue.

+
+ +

Note that all special escape sequences are ignored in quoted strings:

+ +
(* regular strings *)
+let greeting = "Hello, World!\n"
+let superscript_plus = "\u{207A}";;
+val greeting : string = "Hello, World!\n"
+val superscript_plus : string = "⁺"
+
+(* quoted strings *)
+let greeting = {|Hello, World!\n|}
+let superscript_plus = {|\u{207A}|};;
+val greeting : string = "Hello, World!\\n"
+val superscript_plus : string = "\\u{207A}"
+
+ +

In this way you can say they are pretty similar to single-quoted strings in +languages like Perl and Ruby (think 'string').

+ +

Real World OCaml has a nice +example that +illustrates the usefulness of quoted strings:

+ +
let%expect_test _ =
+  let example_html =
+    {|
+    <html>
+      Some random <b>text</b> with a
+      <a href="http://ocaml.org/base">link</a>.
+      And here's another
+      <a href="http://github.com/ocaml/dune">link</a>.
+      And here is <a>link</a> with no href.
+    </html>|}
+  in
+  let soup = Soup.parse example_html in
+  let hrefs = get_href_hosts soup in
+  print_s [%sexp (hrefs : Set.M(String).t)]
+
+ +

As you can see one good use-case for quoted strings is embedding snippets of +code, as those typically tend to have lots of things that would normally need to be +escaped. +And because the delimiters are so flexible you don’t really have to worry about +content that uses {| |} internally - after all you can easily change this to +whatever you want.

+ +
let nested = {xoxo|hello {|world|}|xoxo};;
+val nested : string = "hello {|world|}"
+
+ +

Another good use-case for quoted strings are regular expressions.1 In regular +expressions you will often use backslash characters; it’s easier to use a quoted +string literal {|...|} to avoid having to escape backslashes. For example, the +following expression:

+ +
let r = Str.regexp {|hello \([A-Za-z]+\)|} in
+     Str.replace_first r {|\1|} "hello world"
+
+ +

returns the string “world”.

+ +

If you want a regular expression that matches a literal backslash character, you need to double it: Str.regexp {|\\|}.

+ +

If we use regular string literals (“…”), we will have to escape backslashes, which makes the regular expressions a bit harder the read:

+ +
let r = Str.regexp "hello \\([A-Za-z]+\\)" in
+     Str.replace_first r "\\1" "hello world"
+
+ +

And the regular expression for matching a backslash becomes a quadruple backslash: Str.regexp "\\\\". Pretty ugly, right?

+ +

One more thing. Quoted strings {|...|} can be combined with extension +nodes to +embed foreign syntax fragments. Those fragments can be interpreted by a +preprocessor and turned into OCaml code without requiring escaping quotes. A +syntax shortcut is available for them:

+ +

+{%%foo|...|}               === [%%foo{|...|}]
+let x = {%foo|...|}        === let x = [%foo{|...|}]
+let y = {%foo bar|...|bar} === let y = [%foo{bar|...|bar}]
+
+
+ +

For instance, you can use {%sql|...|} to represent arbitrary SQL statements – +assuming you have a ppx-rewriter that recognizes the %sql extension.

+ +

I have to say I think it’s a bit funny that OCaml’s quoted strings are called +“quoted strings”. It’s not like double-quoted strings (think "string") are +unquoted, right? Pretty sure this name doesn’t help with the discoverability of +this useful feature. Oh, well - naming is hard!

+ +

That’s all I have for you today. Please, share in the comments whether you use +quoted strings and what are some of your favorite use-cases for them. Keep +hacking!

+ +
+
    +
  1. +

    The examples here use the built-in Str library. 

    +
  2. +
+
diff --git a/data/planet/bbatsov/learning-ocaml-regular-expressions.md b/data/planet/bbatsov/learning-ocaml-regular-expressions.md new file mode 100644 index 0000000000..3d960eadd2 --- /dev/null +++ b/data/planet/bbatsov/learning-ocaml-regular-expressions.md @@ -0,0 +1,248 @@ +--- +title: 'Learning OCaml: Regular Expressions' +description: "One of the things that bothered me initially in OCaml was the poor support + for working in regular expressions in the standard library. Technically speaking, + there\u2019s no support for them at all!" +url: https://batsov.com/articles/2025/04/04/learning-ocaml-regular-expressions/ +date: 2025-04-04T11:22:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

One of the things that bothered me initially in OCaml was the poor support for +working in regular expressions in the standard library. +Technically speaking, there’s no support for them at all!

+ +

What do I mean by this? Well, there’s the older Str library that provides support for regular expressions, but it’s:

+ +
    +
  • not really a part of the standard library (it’s bundled with OCaml, but not part of Stdlib)
  • +
  • it doesn’t work with unicode characters, as it treats strings as sequences of bytes
  • +
  • very confusingly named (when I see something named Str I’m thinking of strings)
  • +
+ +

Note: Use #require "str";; in the top-level to load Str.

+ +

Here’s a trivial example using it:

+ +
let text = "hello123world" in
+let re = Str.regexp "[0-9]+" in
+if Str.string_match re text 0 then
+  Printf.printf "Matched: %s\n" (matched_string text)
+else
+  Printf.printf "No match\n";;
+
+Str.global_replace (Str.regexp "[0-9]+") "#" "hello123world456";;
+- : string = "hello#world#"
+
+let re = Str.regexp {|hello \([A-Za-z]+\)|} in
+      Str.replace_first re {|\1|} "hello world"
+- : string = "world"
+
+Str.split (Str.regexp "[ \t]+") "hello world";;
+- : string list = ["hello"; "world"]
+
+ +

I hope the examples are self-explanatory. Str’s API is quite similar to what you’d find in most imperative +languages, which is part of the reason the library is frowned upon.

+ +

Tip: If you find string literals like {|foo bar|} strange, please consult this article.

+ +

I won’t dwell much on Str as few people use it these days, especially if they need to do more +complex tasks with regular expressions. Enter the Re library. +Before we do something with Re we’ll need to install it:

+ +
opam install re
+
+ +

One interesting thing about Re is that it supports various flavors of regular expressions:

+ +
    +
  • Perl-style regular expressions (module Re.Perl);
  • +
  • Posix extended regular expressions (module Re.Posix);
  • +
  • Emacs-style regular expressions (module Re.Emacs);
  • +
  • Shell-style file globbing (module Re.Glob).
  • +
+ +

Okay, shell globbing is not exactly regular expressions, and I’m not sure who would want to use Emacs style regular expressions +outside Emacs, but you sure have options! I’m a big fan of Perl’s regular expressions, so I’ll stick with them going forward.

+ +

Now, let’s see it in action (I encourage to try the examples below in utop):

+ +
#require "re";;
+
+(* basic matching *)
+let re = Re.Perl.re "[0-9]+" |> Re.compile in
+let text = "hello123world" in
+match Re.exec_opt re text with
+| Some group -> Printf.printf "Matched: %s\n" (Re.Group.get group 0)
+| None -> Printf.printf "No match\n"
+;;
+
+(* replace matches *)
+let replace_digits str =
+  let re = Re.Perl.re "[0-9]+" |> Re.compile in
+  Re.replace_string re ~by:"#"
+    str
+;;
+
+print_endline (replace_digits "hello123world456");;
+
+(* use matching groups *)
+let re = Re.Perl.re "(\\w+)-(\\d+)" |> Re.compile in
+match Re.exec_opt re "item-42" with
+| Some group ->
+    let name = Re.Group.get group 1 in
+    let number = Re.Group.get group 2 in
+    Printf.printf "name: %s, number: %s\n" name number
+| None -> print_endline "No match"
+;;
+
+(* composable regular expressions *)
+let word = Re.rep1 Re.wordc;;
+let dash = Re.char '-' ;;
+let digits = Re.rep1 Re.digit;;
+
+let re =
+  Re.seq [word; dash; digits] |> Re.compile
+;;
+
+let input = "hello-123" in
+match Re.exec_opt re input with
+| Some g -> print_endline ("Matched: " ^ Re.Group.get g 0)
+| None -> print_endline "No match"
+;;
+
+(* iterate over all matches *)
+let re = Re.Perl.re "\\d+" |> Re.compile;;
+
+let all_matches str =
+  Re.all re str
+  |> List.iter (fun g -> Printf.printf "Match: %s\n" (Re.Group.get g 0))
+;;
+
+all_matches "a1 b22 c333";;
+
+ +

I hope it’s clear that Re allows you to program in a more functional way. +I’ve barely scratched the surface here, as the library has pretty big API, +that everyone serious about it should eventually explore. +Below is a list of its most useful combinators:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CombinatorMeaning
Re.char cMatch a single char
Re.string sMatch exact string
Re.alt [r1; r2]Alternation (r1 | r2)
Re.seq [r1; r2]Concatenation (r1 r2)
Re.rep rZero or more (r*)
Re.rep1 rOne or more (r+)
Re.opt rOptional (r?)
Re.group rCapture group
Re.compileCompile the regex
+ +

And here’s a brief comparison of Str vs Re:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureStr (legacy)Re (modern)
AvailabilityBuilt-in (kind of)External library (re package)
API StyleImperative, statefulFunctional, composable
Regex FlavorPOSIX-likeMultiple backends (Perl, Str, Emacs, etc.)
Unicode supportPoorBetter (though OCaml string handling is limited)
Match iterationAwkward (search_forward loop)Elegant (Re.all, Re.iter)
ReplacementString onlyFunction or string
Error messagesVagueClear, structured
ComposabilityPoor (regexp strings only)Excellent (regex combinators like seq, alt)
+ +

To sum it up:

+ +
    +
  • Use Str only if you want zero dependencies and can tolerate legacy, clunky APIs.
  • +
  • Use Re if you care about code clarity, safety, composability, and are okay with pulling in an external dependency (which you should be in 2025).
  • +
+ +

That article sat in my backlog for quite a while, as regular expressions were +one of the most frustrating aspects for me when I started to play with OCaml +(Perl and Ruby had really spoiled me on that front), but eventually I kind of +got used to them, so I no longer felt much need to write the article. Still, +I hope some newcomers to OCaml will find it userful!

+ +

That’s all I have for you today. Keep hacking!

diff --git a/data/planet/bbatsov/learning-ocaml-verifying-tail-recursion-with-tailcall.md b/data/planet/bbatsov/learning-ocaml-verifying-tail-recursion-with-tailcall.md new file mode 100644 index 0000000000..6bad3e0f38 --- /dev/null +++ b/data/planet/bbatsov/learning-ocaml-verifying-tail-recursion-with-tailcall.md @@ -0,0 +1,54 @@ +--- +title: 'Learning OCaml: Verifying tail-recursion with @tailcall' +description: "How can you be sure that an OCaml function you wrote is actually tail-recursive? + You can certainly compile the code and look at the generated assembly code, but + that\u2019d be quite the overkill, given there is a much simpler way to do this." +url: https://batsov.com/articles/2024/01/16/learning-ocaml-verifying-tail-recursion-with-tailcall/ +date: 2024-01-16T08:52:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

How can you be sure that an OCaml function you wrote is actually tail-recursive? +You can certainly compile the code and look at the generated assembly code, but that’d be quite the overkill, given there is a much simpler way to do this.

+ +

OCaml 4.03 introduced the @tailcall attribute which will trigger a compiler warning if it’s not placed at an actual tail-call.1 It should be used like this:

+ +
+

(f [@tailcall]) x y warns if f x y is not a tail-call

+
+ +

Here are a couple of trivial examples to help illustrate this:

+ +
(* tail-recursive factorial function *)
+let rec fact1 acc x =
+  if x <= 1 then acc else (fact1 [@tailcall]) (acc * x) (x - 1)
+
+(* non tail-recursive factorial function *)
+let rec fact2 x =
+  if x <= 1 then 1 else x * (fact2 [@tailcall]) (x - 1)
+
+ +

Save the code above in a file named tailcall.ml and compile it with ocamlc:

+ +
$ ocamlc tailcall.ml
+File "./tailcall.ml", line 5, characters 28-55:
+5 |   if x <= 1 then 1 else x * (fact2 [@tailcall]) (x - 1)
+                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Warning 51 [wrong-tailcall-expectation]: expected tailcall
+
+ +

As you can see the compiler properly detected that fact2 is not tail-recursive, as the tail-call is * instead of fact2. +Small, but handy feature that helps you ensure your code works the way you intended it to work.

+ +

That’s all I have for you today. Keep hacking!

+ +
+
    +
  1. +

    Basically the tail-call is the call that triggers the recursion in the function and for a function to be tail-recursive the last call has to be an invocation of the recursive function itself. 

    +
  2. +
+
diff --git a/data/planet/bbatsov/neocaml-a-new-emacs-package-for-ocaml-programming.md b/data/planet/bbatsov/neocaml-a-new-emacs-package-for-ocaml-programming.md new file mode 100644 index 0000000000..5e3bd8de62 --- /dev/null +++ b/data/planet/bbatsov/neocaml-a-new-emacs-package-for-ocaml-programming.md @@ -0,0 +1,128 @@ +--- +title: 'neocaml: a new Emacs package for OCaml programming' +description: "I wasn\u2019t an early adopter of TreeSitter in Emacs, as usually such + big transitions are not smooth and the initial support for TreeSitter in Emacs left + much to be desired. Recently, however, Emacs 30 was released with many improvements + on that front, and I felt the time was right for me to (try to) embrace TreeSitter." +url: https://batsov.com/articles/2025/03/14/neocaml-a-new-emacs-package-for-ocaml-programming/ +date: 2025-03-14T08:01:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

I wasn’t an early adopter of TreeSitter in Emacs, as usually such +big transitions are not smooth and the initial support for TreeSitter in +Emacs left much to be desired. Recently, however, Emacs 30 was released with many +improvements on that front, and I felt the time was right for me to (try to) embrace +TreeSitter.

+ +

I’m the type of person who likes to learn by deliberate practice, that’s why I +wanted to do some work on TreeSitter-powered major modes. I’ve already been a +co-maintainer of +clojure-ts-mode for a while +now, and I picked up the basics around it, but I didn’t spend much time hacking +on it until recently. After spending a bit more time studying the current +implementation of clojure-ts-mode and the various Emacs TreeSitter APIs, I decided to +start a new experimental project from scratch - +neocaml, a TreeSitter-powered package for +OCaml development.1

+ +

Why did I start a new OCaml package, when there are already a few existing out +there? Because caml-mode is ancient (and probably has to be deprecated), and +tuareg-mode is a beast. (it’s very powerful, but also very complex) The time +seems ripe for a modern, leaner, TreeSitter-powered mode for OCaml.

+ +

There have been two other attempts to create TreeSitter-powered +major modes for Emacs, but they didn’t get very far:

+ + + +

Looking at the code of both modes, I inferred that the authors were probably knowledgable in +OCaml, but not very familiar with Emacs Lisp and Emacs major modes in general. +For me it’s the other way around, and that’s what makes this a fun and interesting project for me:

+ +
    +
  • I enjoy working on Emacs packages
  • +
  • As noted above I want to do more work TreeSitter
  • +
  • I really like OCaml and it’s one of my favorite “hobby” languages
  • +
+ +

One last thing - we really need more Emacs packages with fun names! :D Naming is hard, and I’m +notorious “bad” at it!2

+ +

They say that third time’s the charm, and I hope that neocaml will get farther than +the other ocaml-ts-modes. Time will tell!

+ +

I’ve documented the code extensively inline, and in the README you’ll find my development notes detailing +some of my decisions, items that need further work and research, etc. If nothing else - I think +anyone can learn a bit about how TreeSitter works in Emacs and what are the common challenges +that one might face when working with it. To summarize my experience so far:

+ +
    +
  • font-locking (syntax highlighting) with TreeSitter is fairly easy
  • +
  • structured navigation seems reasonably straight-forward as well
  • +
  • the indentation queries are a bit more complicated, but they are definitely not black magic
  • +
+ +

Fundamentally, the main problem is that we still don’t have +easy ways to try out TreeSitter queries in Emacs, so there’s a lot of trial and error involved. (especially when it +comes to indentation logic) My other big problem is that most TreeSitter grammars +have pretty much no documentation, you one has to learn about their AST format +via experimentation (e.g. treesit-explore-mode and treesit-inspect-mode) and +reading their bundled queries for font-locking and indentation. As someone who’s +used to work with Ruby parser I really miss the docs and tools that come with +something like the Ruby parser library.

+ +

What’s the state of project right now? Well, neocaml kind of works right now, +but the indentation logic needs a lot of polish, and I’ve yet to implement +properly structured navigation and some of the newer Emacs TreeSitter APIs +(e.g. things). We can always “cheat” a bit with the indentation, by +delegating it to another Emacs package like ocp-indent.el or even Tuareg, but +I’m hoping to come up with a self-contained TreeSitter implementation in the end +of the day.

+ +

If you’re feeling adventurous you can easily install the package like this:

+ +
M-x package-vc-install <RET> https://github.com/bbatsov/neocaml <RET>
+
+ +

In Emacs 30 you can you use-package to both install the package from GitHub +and configure it:

+ +
(use-package neocaml
+  :vc (:url "https://github.com/bbatsov/neocaml" :rev :newest))
+
+ +

Note: neocaml will auto-install the required TreeSitter grammars the +first time one of the provided major modes is activated.

+ +

Please refer to the README for usage information, like the various configuration +options and interactive commands.

+ +

I’m not sure how much time I’ll be able to spend working on neocaml and how far +will I be able to push it. Perhaps it will never amount to anything, perhaps it +will just be a research platform to bring TreeSitter support to Tuareg. And +perhaps it will become a viable simple, yet modern solution for OCaml +programming in Emacs. The dream is alive!

+ +

Contributions, suggestions and feedback are most welcome. Keep hacking!

+ +
+
    +
  1. +

    I didnt’ name it neocaml-mode intentionally - many Emacs packages contain more things +than just major modes, so I prefer a more generic naming. 

    +
  2. +
  3. +

    On a more serious note - there was never an ocaml-mode, so naming something ocaml-ts-mode is not +strictly needed. But I think an actual ocaml-mode should be blessed by the the maintainers of OCaml, +hosted in the primary GitHub org, and endorsed as a recommended way to program in OCaml with Emacs. +Pretty tall order! 

    +
  4. +
+
diff --git a/data/planet/bbatsov/ocaml-adds-listtake-and-listdrop.md b/data/planet/bbatsov/ocaml-adds-listtake-and-listdrop.md new file mode 100644 index 0000000000..dd59d2ca66 --- /dev/null +++ b/data/planet/bbatsov/ocaml-adds-listtake-and-listdrop.md @@ -0,0 +1,86 @@ +--- +title: OCaml Adds `List.take` and `List.drop` +description: "One of my small issues with OCaml is that the standard library is quite + spartan. Sometimes it misses functions that are quite common in other (similar) + languages. One such example are functions like drop, drop_while, take and take_while + in the List module.1 What\u2019s weird is that the similar Seq module features all + those functions since OCaml 4.14. I believe it was Haskell that + populirized them.\_\u21A9" +url: https://batsov.com/articles/2024/02/23/ocaml-adds-list-take-and-list-drop/ +date: 2024-02-23T07:12:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

One of my small issues with OCaml is that the standard library is quite spartan. +Sometimes it misses functions that are quite common in other (similar) +languages. One such example are functions like drop, drop_while, take and +take_while in the List module.1 What’s weird is that the similar +Seq module features all those functions +since OCaml 4.14.

+ +

Fortunately, that’s finally changing! While perusing the OCaml +changelog a few days ago, I +noticed a reference to a recently merged pull +request that adds the missing List +functions. It’s interesting that this PR is a follow-up to another PR that was a +bit more ambitious and was created way back in Oct +2020. Oh, well - better late than +never, right?

+ +

As you can imagine there’s nothing fancy about the implementation of the new functions:

+ +
let take n l =
+  let[@tail_mod_cons] rec aux n l =
+    match n, l with
+    | 0, _ | _, [] -> []
+    | n, x::l -> x::aux (n - 1) l
+  in
+  if n < 0 then invalid_arg "List.take";
+  aux n l
+
+let drop n l =
+  let rec aux i = function
+    | _x::l when i < n -> aux (i + 1) l
+    | rest -> rest
+  in
+  if n < 0 then invalid_arg "List.drop";
+  aux 0 l
+
+let take_while p l =
+  let[@tail_mod_cons] rec aux = function
+    | x::l when p x -> x::aux l
+    | _rest -> []
+  in
+  aux l
+
+let rec drop_while p = function
+  | x::l when p x -> drop_while p l
+  | rest -> rest
+
+ +

Pretty standard recursive implementations. If you’re not familiar with +@tail_mod_cons - it’s basically tail-call optimization for :: (a.k.a. cons) +in the final position of a recursive function.2

+ +

It seems the new List functions will be shipped with OCaml 5.3. OCaml 5.2 is +not out at the time I’m writing this, but I’m guessing the PR missed the merge +window for 5.2. In the mean time - we can continue to rely on the excellent +Containers +library +for that functionality.

+ +

That’s all I have for you today. Keep hacking!

+ +
+
    +
  1. +

    I believe it was Haskell that populirized them. 

    +
  2. +
  3. +

    See https://v2.ocaml.org/manual/tail_mod_cons.html for more details. 

    +
  4. +
+
diff --git a/data/planet/bbatsov/ocaml-tips-converting-a-string-to-a-list-of-characters.md b/data/planet/bbatsov/ocaml-tips-converting-a-string-to-a-list-of-characters.md new file mode 100644 index 0000000000..5d43e1bb9a --- /dev/null +++ b/data/planet/bbatsov/ocaml-tips-converting-a-string-to-a-list-of-characters.md @@ -0,0 +1,59 @@ +--- +title: 'OCaml Tips: Converting a String to a List of Characters' +description: "While playing with OCaml I was surprised to learn there\u2019s no built-in + function the convert a string to a list of its characters. Admittedly, that\u2019s + not something you need very often, but it does come handy from time to time. There + are many ways to implement such a function ourselves and the one I like the most + makes use of List.init:" +url: https://batsov.com/articles/2022/10/24/ocaml-tips-converting-a-string-to-a-list-of-characters/ +date: 2022-10-24T07:33:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

While playing with OCaml I was surprised to learn there’s no built-in +function the convert a string to a list of its characters. Admittedly, that’s +not something you need very often, but it does come handy from time to time. +There are many ways to implement such a function ourselves and the one I like +the most makes use of List.init:

+ +
let explode_string s = List.init (String.length s) (String.get s);;
+val explode_string : string -> char list = <fun>
+
+explode_string "hello, world!";;
+- : char list = ['h'; 'e'; 'l'; 'l'; 'o'; ','; ' '; 'w'; 'o'; 'r'; 'l'; 'd'; '!']
+
+ +

I went with the name explode_string as the name explode is often used to describe this type of operation (with implode being the name of the inverse operation).

+ +

Searching for the signature string -> char list on Sherlodoc reveals that many libraries offer some version of the above function. +Perhaps one day we’ll have something like String.to_list in the standard library.

+ +

By the way, it’s also pretty easy to define the inverse operation - namely creating a string out of a list of characters:

+ +
let implode_char_list l = String.of_seq (List.to_seq l);;
+val implode_char_list : char list -> string = <fun>
+
+implode_char_list (explode_string "hello");;
+- : string = "hello"
+
+ +

Note that List.init was added in OCaml 4.06 and String.of_seq was added in OCaml 4.07.

+ +

Keep in mind that lists of chars are quite memory inefficient, as each character +takes 4 bytes (64 bits) on a modern 64 bit CPU.1 When you factor the pointers to +the next element in the list, each character is effectively taking 8 bytes, +which is pretty far from the memory efficiency of a string. The take away is that +you should avoid using them if you’re dealing with large data sets.

+ +

That’s all I have for you today. Keep hacking!

+ +
+
    +
  1. +

    You can learn more about OCaml’s runtime memory layout here

    +
  2. +
+
diff --git a/data/planet/bbatsov/ocaml-tips-implementing-a-range-function.md b/data/planet/bbatsov/ocaml-tips-implementing-a-range-function.md new file mode 100644 index 0000000000..8a6c5b8234 --- /dev/null +++ b/data/planet/bbatsov/ocaml-tips-implementing-a-range-function.md @@ -0,0 +1,160 @@ +--- +title: 'OCaml Tips: Implementing a range Function' +description: "Lots of programming languages have some built-in range functionality, + that\u2019s typically used to generate a list/array of integer numbers. Here are + a couple of examples from Ruby and Clojure:" +url: https://batsov.com/articles/2022/10/31/ocaml-tips-implementing-a-range-function/ +date: 2022-10-31T06:45:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

Lots of programming languages have some built-in range functionality, that’s +typically used to generate a list/array of integer numbers. Here are +a couple of examples from Ruby and Clojure:

+ +
# This is Ruby
+
+(1..10).to_a
+# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+
+(1..10).filter(&:even?)
+# => [2, 4, 6, 8, 10]
+
+# And some related functionality, that doesn't use literal ranges
+5.downto(1).to_a # => [5, 4, 3, 2, 1]
+
+10.step(1, -2).to_a # => [10, 8, 6, 4, 2]
+
+ +
;; This is Clojure
+
+(range 1 10)
+;; => (1 2 3 4 5 6 7 8 9)
+
+(range 1 10 2)
+;; => (1 3 5 7 9)
+
+(range 100 0 -10)
+;; (100 90 80 70 60 50 40 30 20 10)
+
+ +

Ruby has a special syntax for ranges (.. and ...) and Clojure provides +a range function to generate ranges (basically a sequences of integer numbers). +I’m pretty sure you’ve seen something like this. Not the most useful function in +the world for sure, but it’s handy from time to time.

+ +

There are many ways we can implement something similar in OCaml, with the +simplest one probably being to use List.init internally:

+ +
(* simplest/shortest possible version *)
+let range i = List.init i succ
+
+range 10
+- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
+
+(* a version with some boundaries *)
+let range from until =
+  List.init (until - from) (fun i -> i + from)
+
+range 1 10
+- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9]
+
+range 5 15
+- : int list = [5; 6; 7; 8; 9; 10; 11; 12; 13; 14]
+
+(* let's name this -- for good measure *)
+let (--) = range
+
+1 -- 10
+- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9]
+
+(* you can also consider using the names --> and --< for inclusive and exclusive ranges *)
+
+ +

The above implementations are super basic and have a few quirks (e.g. the second +implementation doesn’t allow setting the step and it can’t handle descending +ranges), but they mostly get the job done. A more full-featured implementation +would look something like this:

+ +
let range ?(from=1) ?(step=1) until =
+  let cmp = match step with
+    | i when i < 0 -> (>)
+    | i when i > 0 -> (<)
+    | _ -> raise (Invalid_argument "step cannot be 0")
+  in
+  Seq.unfold (function
+        | i when cmp i until -> Some (i, i + step)
+        | _ -> None
+    ) from
+
+ +

This function has a few advantages over the implementations so far:

+ +
    +
  • It uses optional labeled arguments (from and step)
  • +
  • It allows us to set the step explicitly
  • +
  • It handles descending ranges
  • +
  • It’s implemented in terms of Seq, meaning it’s lazy
  • +
+ +

Note: The order of the arguments in the definition matters, as optional +arguments are only filled in once a positional argument after them has been +applied. If ?step is the last argument that can never happen.

+ +

And here’s how using it in practice looks:

+ +
range 10 |> List.of_seq;;
+- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9]
+
+range ~from:10 20 |> List.of_seq;;
+- : int list = [10; 11; 12; 13; 14; 15; 16; 17; 18; 19]
+
+range 100 ~step:10 |> List.of_seq;;
+- : int list = [1; 11; 21; 31; 41; 51; 61; 71; 81; 91]
+
+range ~from:5 20 ~step:5 |> List.of_seq;;
+- : int list = [5; 10; 15]
+
+range ~from:20 5 ~step:(-5) |> List.of_seq;;
+- : int list = [20; 15; 10]
+
+ +

Now we’re talking!

+ +

One funny thing to note is that originally I wanted to use from and to as +the parameter names, but I couldn’t use to as it’s a keyword is OCaml:

+ +
for variable = start_value to end_value do
+  expression
+done
+
+ +

I keep forgetting about this, as I never use those for loops and Clojure has +spoiled me with its extremely small set of keywords.

+ +

Another funny bit worth sharing, as that one of the test cases for Seq.unfold is +exactly a trivial implementation of range:

+ +
(* unfold *)
+let () =
+  let range first last =
+    let step i = if i > last then None
+                 else Some (i, succ i) in
+    Seq.unfold step first
+  in
+  begin
+    assert ([1;2;3] = !!(range 1 3));
+    assert ([] = !!(range 1 0));
+  end
+;;
+
+ +

A quick +search on +Sherlodoc reveals a ton of similar functions in many OCaml libraries, so clearly +there’s some use for a range function in one form or another.

+ +

That’s all I have for you today. Keep hacking!

diff --git a/data/planet/bbatsov/ocamls-standard-library-stdlib.md b/data/planet/bbatsov/ocamls-standard-library-stdlib.md new file mode 100644 index 0000000000..d1b6f6cccd --- /dev/null +++ b/data/planet/bbatsov/ocamls-standard-library-stdlib.md @@ -0,0 +1,250 @@ +--- +title: "OCaml\u2019s Standard Library (`Stdlib`)" +description: "Every programming language comes with some \u201Cbatteries\u201D included + - mostly in the form of its standard library. That\u2019s typically all of the functionality + that\u2019s available out-of-the-box, without the need to install additional libraries. + (although the definition varies from language to language) Usually standard libraries + are pretty similar, but I think that OCaml\u2019s a bit \u201Cweird\u201D and slightly + surprising in some regards, so I decided to write down a few thoughts on it and + how to make the best of it." +url: https://batsov.com/articles/2025/03/14/ocaml-s-standard-library/ +date: 2025-03-14T09:18:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

Every programming language comes with some “batteries” included - +mostly in the form of its standard library. That’s typically all +of the functionality that’s available out-of-the-box, without the need +to install additional libraries. (although the definition varies from +language to language) Usually standard libraries are pretty similar, +but I think that OCaml’s a bit “weird” and slightly surprising in some +regards, so I decided to write down a few thoughts on it and how to +make the best of it.

+ +

OCaml’s standard library is called Stdlib and it’s the source of much +“controversy” in the OCaml community. Historically Stdlib was focused only the +needs of the OCaml compiler (many people called it “the compiler library” for +that reason) and it was very basic when it comes to the functionality that it +provided. This is part of the reason why libraries like Jane Street’s Base +and Core (alternatives to Stdlib), and OCaml Containers (complementary +extensions to Stdlib) become so popular in the OCaml community.

+ +

From what I gathered, the compiler authors felt it was the responsibility of the +users of the language to find (or create) the right libraries for their +use-cases and preferred to keep the standard library as lean as possible. I get +their reasoning, but I think this backfired to some extent, as it’s not +something that many newcomers to a language would expect. The standard library +was definitely a point of surprise and disappointment for me when playing with +OCaml for the first time. I still remember how surprised I was that the book +Real World OCaml began with the instructions +to replace the built-in standard library with the more full-featured Base and +Core libraries. I was used to fairly minimal standard library from my time +with Clojure, but OCaml really outdid Clojure in this regard!

+ +

These days, however, I’ve noticed an increased focus on aligning the Stdlib +functionality with the expectations of most programmers. That’s obvious when you +check the recent OCaml releases, that feature many additions to it:

+ +
    +
  • OCaml 5.1: 57 new standard library functions.
  • +
  • OCaml 5.2: Around 20 new functions added to the standard library.
  • +
  • OCaml 5.3: Around 20 new functions in the standard library (in the Domain, Dynarray, Format, List, Queue, Sys, and Uchar modules).
  • +
+ +

I’ve written about some of those recent additions in the past - e.g. List.take and +List.drop and I +think they’ll be quite helpful for newcomers to the language.

+ +

I think the trend to extend Stdlib started somewhere around OCaml +4.07 and has accelerated recently. +That probably won’t surprise long-term users of OCaml, as the Stdlib +module didn’t even exist before. I’ll come back to this topic later in the article.

+ +

Exploring Stdlib

+ +

The Stdlib module is +automatically opened at the beginning of each compilation. All components of +this module can therefore be referred by their short name, without prefixing +them by Stdlib.

+ +

In particular, it provides the basic operations over the built-in types +(numbers, booleans, byte sequences, strings, exceptions, references, lists, +arrays, input-output channels, …) and the standard library modules. +In OCaml 5.3 Stdlib consists of the following modules:

+ +
    +
  • Arg: parsing of command line arguments
  • +
  • Array: array operations
  • +
  • ArrayLabels: array operations (with labels)
  • +
  • Atomic: atomic references
  • +
  • Bigarray: large, multi-dimensional, numerical arrays
  • +
  • Bool: boolean values
  • +
  • Buffer: extensible buffers
  • +
  • Bytes: byte sequences
  • +
  • BytesLabels: byte sequences (with labels)
  • +
  • Callback: registering OCaml values with the C runtime
  • +
  • Char: character operations
  • +
  • Complex: complex numbers
  • +
  • Condition: condition variables to synchronize between threads
  • +
  • Domain: Domain spawn/join and domain local variables
  • +
  • Digest: MD5 message digest
  • +
  • Dynarray: Dynamic arrays
  • +
  • Effect: deep and shallow effect handlers
  • +
  • Either: either values
  • +
  • Ephemeron: Ephemerons and weak hash table
  • +
  • Filename: operations on file names
  • +
  • Float: floating-point numbers
  • +
  • Format: pretty printing
  • +
  • Fun: function values
  • +
  • Gc: memory management control and statistics; finalized values
  • +
  • Hashtbl: hash tables and hash functions
  • +
  • In_channel: input channels
  • +
  • Int: integers
  • +
  • Int32: 32-bit integers
  • +
  • Int64: 64-bit integers
  • +
  • Lazy: deferred computations
  • +
  • Lexing: the run-time library for lexers generated by ocamllex
  • +
  • List: list operations
  • +
  • ListLabels: list operations (with labels)
  • +
  • Map: association tables over ordered types
  • +
  • Marshal: marshaling of data structures
  • +
  • MoreLabels: include modules Hashtbl, Map and Set with labels
  • +
  • Mutex: locks for mutual exclusion
  • +
  • Nativeint: processor-native integers
  • +
  • Oo: object-oriented extension
  • +
  • Option: option values
  • +
  • Out_channel: output channels
  • +
  • Parsing: the run-time library for parsers generated by ocamlyacc
  • +
  • Printexc: facilities for printing exceptions
  • +
  • Printf: formatting printing functions
  • +
  • Queue: first-in first-out queues
  • +
  • Random: pseudo-random number generator (PRNG)
  • +
  • Result: result values
  • +
  • Scanf: formatted input functions
  • +
  • Seq: functional iterators
  • +
  • Set: sets over ordered types
  • +
  • Semaphore: semaphores, another thread synchronization mechanism
  • +
  • Stack: last-in first-out stacks
  • +
  • StdLabels: include modules Array, List and String with labels
  • +
  • String: string operations
  • +
  • StringLabels: string operations (with labels)
  • +
  • Sys: system interface
  • +
  • Type: type introspection
  • +
  • Uchar: Unicode characters
  • +
  • Unit: unit values
  • +
  • Weak: arrays of weak pointers
  • +
+ +

Lots of good stuff here! Sure, it’s not anything like the standard libraries of +languages like Ruby, Python or Java, but you have the basics covered, at +least to some extent.

+ +

Note that unlike the core Stdlib module, sub-modules are not automatically +“opened” when compilation starts, or when the toplevel system (e.g. ocaml or +utop) is launched. Hence it is necessary to use qualified identifiers +(e.g. List.map) to refer to the functions provided by these modules, or to add +open directives.

+ +

One thing I found somewhat peculiar at first was the presence of two versions of +some standard library modules - e.g. List and ListLabels. Both of them have +the same functions, but the ListLabels module makes heavy use of labeled +parameters. I’m not sure what’s the reasoning behind this, but I’m guessing this +was influenced by the Base library, that’s using labels everywhere +pervasively. Here are a few examples:

+ +
(* Using List module *)
+let squares_list = List.map (fun x -> x * x) [1; 2; 3; 4; 5]
+(* Result: [1; 4; 9; 16; 25] *)
+
+(* Using ListLabels module *)
+let squares_list_labels = ListLabels.map [1; 2; 3; 4; 5] ~f:(fun x -> x * x)
+(* Result: [1; 4; 9; 16; 25] *)
+
+(* Using List module *)
+let sum_list = List.fold_left (+) 0 [1; 2; 3; 4; 5]
+(* Result: 15 *)
+
+(* Using ListLabels module *)
+let sum_list_labels = ListLabels.fold_left [1; 2; 3; 4; 5] ~init:0 ~f:(+)
+(* Result: 15 *)
+
+ +

The labeled arguments in ListLabels make it clear what each parameter means - +e.g. ~init for the initial value and ~f for the folding function. I’m not +sure how I feel about labeled arguments in general, as in most cases I don’t +think they are really needed, but you’ve got the option if you want it.

+ +

One notable omission from Stdlib is some module for dealing with regular +expressions. OCaml bundles the (controversial) +str module, but it’s not part of +Stdlib and you have to link it to your applications manually:

+ +
ocamlc other options -I +str str.cma other files
+ocamlopt other options  -I +str str.cmxa other files
+
+ +

Not to mention that you probably want to use something different instead. (e.g. re)

+ +

Note: The documentation of +Stdlib is excellent and I highly +recommend everyone to peruse it.

+ +

Base or Stdlib?

+ +

A lot of people might be wondering whether to use Jane Street’s standard library +Base or Stdlib? I’m guessing there was a time when Base offered bigger +advantages over Stdlib, but today it’s harder to recommend Base over +Stdlib. Especially when you factor in the library OCaml +Containers which provides numerous +extensions to Stdlib.

+ +

My advice for most newcomers would be to start with Stdlib and mix in Containers if +needed. If you deem they are not enough for you - feel free to explore Base at this point.

+ +

I think Base (and Core) are excellent and battle-tested libraries, but I still think +it’s a good idea for everyone to be familiar with OCaml’s “native” standard library. And for +all of us to be pushing to make it better, of course.

+ +

A note about the core library

+ +

Sometimes you might hear mentions of OCaml’s “core library” (not to be confused +with Core by Jane Street) and you might wonder what’s that exactly.

+ +

Well, the “core library” is composed of declarations for built-in types and +exceptions, plus the module Stdlib that provides basic operations on these +built-in types.

+ +

You can learn more about the core library here.

+ +

A note about Pervasives

+ +

Early on in my OCaml journey I’d find references here and there to a library +named Pervasives, that sounded more or less like a standard library. +Turns out that Pervasives got renamed to Stdlib in OCaml 4.07. Here are a few highlights +from the release notes of this quite important release:

+ +
    +
  • The standard library is now packed into a module called Stdlib, which is +open by default. This makes it easier to add new modules to the standard +library without clashing with user-defined modules.
  • +
  • The Bigarray module is now part of the standard library.
  • +
  • The modules Seq, Float were added to the standard library.
  • +
+ +

I know Pervasives was kept around for a while for backwards compatibility and it seems it’s no +longer present in OCaml 5.x.

+ +

Epilogue

+ +

OCaml’s Stdlib is often cited as a reason why the language is not popular, and +I think that’s a valid argument. Still, it seems to me that lately Stdlib has +been moving in the right direction, and the out-of-the-box OCaml experience got +improved because of this. I can only hope that this trend will continue and that +as a result OCaml will become more beginner-friendly and more useful out-of-the-box.

+ +

What improvements would you like to see there going forward?

+ +

That’s all I have for you today. Keep hacking!

diff --git a/data/planet/bbatsov/reading-files-in-ocaml.md b/data/planet/bbatsov/reading-files-in-ocaml.md new file mode 100644 index 0000000000..cdf4c6caa5 --- /dev/null +++ b/data/planet/bbatsov/reading-files-in-ocaml.md @@ -0,0 +1,165 @@ +--- +title: Reading Files in OCaml +description: "One thing I\u2019ve noticed on my journey to learn OCaml was that reading + (text) files wasn\u2019t as straightforward as with many other programming languages. + To give you some point of reference - here\u2019s how easy it is to do this in Ruby:" +url: https://batsov.com/articles/2022/11/27/reading-files-in-ocaml/ +date: 2022-11-27T07:52:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

One thing I’ve noticed on my journey to learn OCaml was that reading (text) files wasn’t as +straightforward as with many other programming languages. To give you some point +of reference - here’s how easy it is to do this in Ruby:

+ +
# read entire file to string
+content = File.read(filename)
+
+# read lines into an array of lines
+lines = File.readlines(filename)
+
+# process lines one at a time (memory efficient when dealing with large files)
+File.foreach(filename) { |line| puts line }
+
+ +

In my beloved Clojure the situation is similar:

+ +
;; read entire file into string
+(slurp filename)
+
+;; process lines one at a time
+(use 'clojure.java.io)
+
+(with-open [rdr (reader filename)]
+  (doseq [line (line-seq rdr)]
+    (println line)))
+
+ +

Basically there are three common operations when +dealing with text files:

+ +
    +
  • reading the whole contents as a single string
  • +
  • reading the whole contents of a collection of lines (often that’s just a slight variation of the previous operation)
  • +
  • reading and processing lines one by one (useful when dealing with large files)
  • +
+ +

When I had to play with files in OCaml for the first time I did some digging +around and I noticed that many people were either rolling out their own +read_lines function based on the built-in input_line function or using Jane +Street’s Base library.

+ +
(* Using Base *)
+open Core.Std
+let contents = In_channel.read_all file
+let lines = In_channel.read_lines file
+
+(* homemade read_lines that gathers all lines in a list *)
+let read_lines name : string list =
+  let ic = open_in name in
+  let try_read () =
+    try Some (input_line ic) with End_of_file -> None in
+  let rec loop acc = match try_read () with
+    | Some s -> loop (s :: acc)
+    | None -> close_in ic; List.rev acc in
+  loop []
+
+let lines = read_lines filename
+
+(* homemade read_lines that processes each line *)
+let read_lines file process =
+  let in_ch = open_in file in
+  let rec read_line () =
+    let line = try input_line in_ch with End_of_file -> exit 0
+    in (* process line in this block, then read the next line *)
+       process line;
+       read_line ();
+in read_line ()
+
+read_lines filename print_endline
+
+ +

Obviously, this gets the job done, but I was quite surprised such basic +operations are not covered in the standard library. Turns out, however, that the +situation has changed recently with OCaml 4.14 with the introduction of the +module In_channel:1

+ +
(* read the entire file *)
+let read_file file =
+  In_channel.with_open_bin file In_channel.input_all
+
+(* read lines *)
+let read_lines file =
+  let contents = In_channel.with_open_bin file In_channel.input_all in
+  String.split_on_char '\n' contents
+
+List.iter print_endline (read_lines filename)
+
+ +

While you still need to roll out your own read_file and read_lines +functions, the implementation is significantly simpler than before. Even more +importantly, the code is now more reliable as noted by Daniel Bünzli:2

+ +
+

Be careful, input_line is a footgun and has led to more than one bug out there – along with open_in and open_out defaulting to text mode and thus lying by default about your data.

+ +

input_line will never report an empty final line and performs newline translations if your channel is in text mode. This means you can’t expect to recover the exact file contents you just read by doing String.concat "\n" on the lines you input with input_line.

+ +

Also of course it doesn’t help with making sure you correctly close your channels and don’t leak them in case of exception. The new functions finally make that a no brainer.

+
+ +

Note: Daniel is referring to functions in Stdlib. They should not be confused with similarly named +functions in the new In_channel module.

+ +

You can also use In_channel.input_line to read file contents line by line and +avoid excessive memory allocation. I’m still missing something like Clojure’s +line-seq that create a lazy seq from which you can obtain the file lines, but +I guess this should be doable in OCaml one way or another.3

+ +

One interesting library that I’ve discovered was Iter and it particular its module Iter.IO. It provides a basic interface to manipulate files as iterator of chunks/lines. The iterators take care of opening and closing files properly; every time one iterates over an iterator, the file is opened/closed again. Here’s are a few examples from the library’s documentation:

+ +
(* Example: copy a file "a" into file "b", removing blank lines: *)
+Iterator.(IO.lines_of "a" |> filter (fun l -> l <> "") |> IO.write_lines "b")
+
+(* By chunks of 4096 bytes: *)
+Iterator.IO.(chunks_of ~size:4096 "a" |> write_to "b")
+
+(* Read the lines of a file into a list: *)
+Iterator.IO.lines "a" |> Iterator.to_list
+
+ +

Cool stuff! I’ll make sure to explore further at some point.

+ +

Perhaps the takeaway for you today is to use libraries like Base and +Containers instead of relying solely on the standard library, perhaps it’s +not. I’ll leave that for you to decide. If you decide to stick with the standard +library - I encourage you to peruse the documentation of +In_channel to learn more about the +functions it offers and the advantages of using it over the legacy input_line +function.

+ +

I really wish that someone would update OCaml’s page on file +manipulation to include coverage of +the OCaml 4.14 functionality (perhaps I’ll do this myself). I’m guessing this +outdated page and other legacy docs are sending a lot of people in the wrong +direction, which was the main reason I’ve decided to write this article.

+ +

That’s all I have for you today. Keep hacking!

+ +

Update: The article generated a nice discussion on Reddit that you may want to peruse.

+ diff --git a/data/planet/bbatsov/simple-ways-to-run-ocaml-code.md b/data/planet/bbatsov/simple-ways-to-run-ocaml-code.md new file mode 100644 index 0000000000..2aba98bc9e --- /dev/null +++ b/data/planet/bbatsov/simple-ways-to-run-ocaml-code.md @@ -0,0 +1,123 @@ +--- +title: Simple Ways to Run OCaml Code +description: "When people think of OCaml they are usually thinking of compiling code + to a binary before they are able to run it. While most OCaml code is indeed compiled + to binaries, you don\u2019t really need to do this, especially while you\u2019re + learning the language and are mostly playing with small exercises." +url: https://batsov.com/articles/2025/02/23/simple-ways-to-run-ocaml-code/ +date: 2025-02-23T18:49:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

When people think of OCaml they are usually thinking of compiling code to a +binary before they are able to run it. While most OCaml code is indeed compiled +to binaries, you don’t really need to do this, especially while you’re learning +the language and are mostly playing with small exercises.

+ +

Imagine you have something like this in a file named hello.ml:

+ +
let () = print_endline "Hello, world!"
+
+ +

You can compile this if you want, but you can also run it directly with OCaml’s +interpreter ocaml:

+ +
$ ocaml hello.ml 
+Hello, world!
+
+ +

This approach should be familiar to anyone who has ever used a scripting +language like Perl, Python, Ruby or JavaScript. You can do the same with utop +as well:

+ +
$ utop hello.ml 
+Hello, world!
+
+ +

Of course, one can argue that it’s just as simple to start utop and then +do #use "hello.ml" from it. Feel free to do whatever works best for you.

+ +

You can take things one step further like this:

+ +
#!/usr/bin/env ocaml
+let () = print_endline "Hello, world!"
+
+ +

Now you can make this file an executable script and run it directly:

+ +
$ chmod +x hello.ml
+$ ./hello.ml
+Hello, world!
+
+ +

While this approach should be used mostly when dealing with code that doesn’t +use external libraries, there’s nothing preventing you from doing so:

+ +
#use "topfind";;
+#require "package_name";;
+(* Your OCaml code here *)
+
+ +

This should be familiar to everyone who has required any packages in utop. +topfind is a file that ocamlfind installs +in the standard library, so that it can be used from the toplevel. +Don’t forget to install ocamlfind first:

+ +
opam install ocamlfind
+
+ +

One last thing before we wrap up - you might be wondering about the use +of let () in the simple examples I’ve provided. Technically that’s not +needed, but you have to keep in mind that when you have multiple expressions in +the source files with boundaries that the compiler can’t infer you’ll need to +separate those with ;;. Using let for everything eliminates the need for this:

+ +
#!/usr/bin/env ocaml
+let () = print_endline "Hello, world!"
+
+let () = print_endline "Bye, world!"
+
+ +

The example above works. The one below, however, doesn’t:

+ +
#!/usr/bin/env ocaml
+print_endline "Hello, world!"
+
+print_endline "Bye, world!"
+
+ +

It will result in a syntax error, because to OCaml this code is basically one expression. +To fix this will need to add ;; to help the compiler:

+ +
#!/usr/bin/env ocaml
+print_endline "Hello, world!";;
+
+print_endline "Bye, world!";;
+
+ +

If you know that you can also use ; to separate expressions that are +evaluation only for their side effects (like print_endline) you might be +tempted to write instead the following:

+ +
#!/usr/bin/env ocaml
+print_endline "Hello, world!";
+print_endline "Bye, world!";;
+
+ +

I’m not a big fan of this at the top-level, though, as it’s intended to be +used mostly in bindings:

+ +
let a = 1 in
+let b = 2 in
+print_int a;
+print_int b;
+a + b
+
+ +

If you have any other tips on running simple OCaml programs, please +share those in the comments.

+ +

That’s all I have for you today. Keep hacking!

diff --git a/data/planet/bbatsov/why-f.md b/data/planet/bbatsov/why-f.md new file mode 100644 index 0000000000..ac4c549622 --- /dev/null +++ b/data/planet/bbatsov/why-f.md @@ -0,0 +1,484 @@ +--- +title: Why F#? +description: "If someone had told me a few months ago I\u2019d be playing with .NET + again after a 15+ years hiatus I probably would have laughed at this.1 Early on + in my career I played with .NET and Java, and even though .NET had done some things + better than Java (as it had the opportunity to learn from some early Java mistakes), + I quickly settled on Java as it was a truly portable environment. I + had some C# courses in the university and I wrote my bachelor\u2019s thesis in C#. + It was a rewrite of Arch Linux\u2019s pacman, running on Mono. This was way back + in 2007.\_\u21A9" +url: https://batsov.com/articles/2025/03/30/why-fsharp/ +date: 2025-03-30T14:54:00-00:00 +preview_image: https://batsov.com/assets/images/bozhidar_avatar.jpg +authors: +- Bozhidar Batsov +source: +--- + +

If someone had told me a few months ago I’d be playing with .NET again after a +15+ years hiatus I probably would have laughed at this.1 Early on in my +career I played with .NET and Java, and even though .NET had done some things +better than Java (as it had the opportunity to learn from some early Java +mistakes), I quickly settled on Java as it was a truly portable environment.

+ +

I guess everyone who reads my blog knows that in the past few years I’ve been +playing on and off with OCaml and I think it’s safe to say that it has become +one of my favorite programming languages - alongside the likes of Ruby and +Clojure. My work with OCaml drew my attention recently to F#, an ML targeting +.NET, developed by Microsoft. The functional counterpart of the +(mostly) object-oriented C#. The newest ML language created…

+ +

F# 1.0 was officially released in May 2005 by Microsoft Research. It was +initially developed by Don Syme at Microsoft Research in Cambridge and evolved +from an earlier research project called “Caml.NET,” which aimed to bring OCaml +to the .NET platform.2 F# was officially moved from Microsoft Research to +Microsoft (as part of their developer tooling division) in 2010 (timed +with the release of F# 2.0).

+ +

F# has been steadily evolving since those early days and the most recent release +F# 9.0 was +released in November 2024. It seems only appropriate that F# would come to my +attention in the year of its 20th birthday!

+ +

There were several reasons why I wanted to try out F#:

+ +
    +
  • .NET became open-source and portable a few years ago and I wanted to check the progress on that front
  • +
  • I was curious if F# offers any advantages over OCaml
  • +
  • I’ve heard good things about the F# tooling (e.g. Rider and Ionide)
  • +
  • I like playing with new programming languages
  • +
+ +

Below you’ll find my initial impressions for several areas.

+ +

The Language

+ +

As a member of the ML family of languages, the syntax won’t surprise +anyone familiar with OCaml. As there are quite few people familiar with +OCaml, though, I’ll mention that Haskell programmers will also feel right at +home with the syntax. And Lispers.

+ +

For everyone else - it’d be fairly easy to pick up the basics.

+ +
printfn "Hello, World!"
+
+let greet name =
+    printfn "Hello, %s!" name
+
+greet "World"
+
+type Shape =
+    | Circle of radius: float
+    | Rectangle of width: float * height: float
+
+let area shape =
+    match shape with
+    | Circle radius -> System.Math.PI * radius * radius
+    | Rectangle (width, height) -> width * height
+
+let circle = Circle 5.0
+let rectangle = Rectangle(4.0, 3.0)
+
+printfn "Circle area: %f" (area circle)
+printfn "Rectangle area: %f" (area rectangle)
+
+ +

Nothing shocking here, right?

+ +

Here’s another slightly more involved example:

+ +
open System
+
+// Sample data - simple sales records
+type SalesRecord = { Date: DateTime; Product: string; Amount: decimal; Region: string }
+
+// Sample dataset
+let sales = [
+    { Date = DateTime(2023, 1, 15); Product = "Laptop"; Amount = 1200m; Region = "North" }
+    { Date = DateTime(2023, 2, 3);  Product = "Phone";  Amount = 800m;  Region = "South" }
+    { Date = DateTime(2023, 1, 20); Product = "Tablet"; Amount = 400m;  Region = "North" }
+    { Date = DateTime(2023, 2, 18); Product = "Laptop"; Amount = 1250m; Region = "East" }
+    { Date = DateTime(2023, 1, 5);  Product = "Phone";  Amount = 750m;  Region = "West" }
+    { Date = DateTime(2023, 2, 12); Product = "Tablet"; Amount = 450m;  Region = "North" }
+    { Date = DateTime(2023, 1, 28); Product = "Laptop"; Amount = 1150m; Region = "South" }
+]
+
+// Quick analysis pipeline
+let salesSummary =
+    sales
+    |> List.groupBy (fun s -> s.Product)                          // Group by product
+    |> List.map (fun (product, items) ->                          // Transform each group
+        let totalSales = items |> List.sumBy (fun s -> s.Amount)
+        let avgSale = totalSales / decimal (List.length items)
+        let topRegion =
+            items
+            |> List.groupBy (fun s -> s.Region)                   // Nested grouping
+            |> List.maxBy (fun (_, regionItems) ->
+                regionItems |> List.sumBy (fun s -> s.Amount))
+            |> fst
+
+        (product, totalSales, avgSale, topRegion))
+    |> List.sortByDescending (fun (_, total, _, _) -> total)      // Sort by total sales
+
+// Display results
+salesSummary
+|> List.iter (fun (product, total, avg, region) ->
+    printfn "%s: $%M total, $%M avg, top region: %s"
+        product total avg region)
+
+ +

Why don’t you try saving the snippet above in a file called Sales.fsx and running it like this:

+ +
dotnet fsi Sales.fsx
+
+ +

Now you know that F# is a great choice for ad-hoc scripts! Also, running dotnet fsi by itself +will pop an F# REPL where you can explore the language at your leisure.

+ +

I’m not going to go into great details here, as much of what I wrote about OCaml +here applies to F# as well. +I’d also suggest this quick tour of F# +to get a better feel for its syntax.

+ +

One thing that made a good impression to me is the focus of the language designers on +making F# approachable to newcomers, by providing a lot of small quality of life improvements +for them. Below are few examples, that probably don’t mean much to you, but would mean something +to people familiar with OCaml:

+ +
// line comments
+(* the classic ML comments are around as well *)
+
+// mutable values
+let mutable x = 5
+x <- 6
+
+// ranges and slices
+let l = [1..2..10]
+name[5..]
+
+// C# method calls look pretty natural
+let name = "FOO".ToLower()
+
+// operators can be overloaded for different types
+let string1 = "Hello, " + "world"
+let num1 = 1 + 2
+let num2 = 1.0 + 2.5
+
+// universal printing
+printfn "%A" [1..2..100]
+
+ +

I guess some of those might be controversial, depending on whether you’re a language purist or not, +but in my book anything that makes MLs more popular is a good thing.

+ +

Did I also mention it’s easy to work with unicode strings and regular expressions?

+ +

Often people say that F# is mostly a staging ground for future C# features, and perhaps that’s true. +I haven’t observed both languages long enough to have my own opinion on the subject, but I was impressed +to learn that async/await (of C# and later JavaScript fame) originated in… F# 2.0.

+ +
+

It all changed in 2012 when C#5 launched with the introduction of what has now +become the popularized async/await keyword pairing. This feature allowed you to +write code with all the benefits of hand-written asynchronous code, such as not +blocking the UI when a long-running process started, yet read like normal +synchronous code. This async/await pattern has now found its way into many +modern programming languages such as Python, JS, Swift, Rust, and even C++.

+ +

F#’s approach to asynchronous programming is a little different from async/await +but achieves the same goal (in fact, async/await is a cut-down version of F#’s +approach, which was introduced a few years previously, in F#2).

+ +

– Isaac Abraham, F# in Action

+
+ +

Time will tell what will happen, but I think it’s unlikely that C# will ever be able to fully replace F#.

+ +

I’ve also found this encouraging comment from 2022 that Microsoft might be willing to invest more in F#:

+ +
+

Some good news for you. After 10 years of F# being developed by 2.5 people +internally and some random community efforts, Microsoft has finally decided to +properly invest in F# and created a full-fledged team in Prague this +summer. I’m a dev in this team, just like you I was an F# fan for many years +so I am happy things got finally moving here.

+
+ +

Looking at the changes in F# 8.0 and F 9.0, it seems the new full-fledged team +has done some great work!

+ +

Ecosystem

+ +

It’s hard to assess the ecosystem around F# after such a brief period, but overall it seems to +me that there are fairly few “native” F# libraries and frameworks out there and most people +rely heavily on the core .NET APIs and many third-party libraries and frameworks geared towards C#. +That’s a pretty common setup when it comes to hosted languages in general, so nothing surprising here as well.

+ +

If you’ve ever used another hosted language (e.g. Scala, Clojure, Groovy) then you probably know what +to expect.

+ +

Awesome F# keeps track of popular F# libraries, tools and frameworks. I’ll highlight here the web development and data science libraries:

+ +

Web Development

+ +
    +
  • Giraffe: A lightweight library for building web applications using ASP.NET Core. It provides a functional approach to web development.
  • +
  • Suave: A simple and lightweight web server library with combinators for routing and task composition. (Giraffe was inspired by Suave)
  • +
  • Saturn: Built on top of Giraffe and ASP.NET Core, it offers an MVC-style framework inspired by Ruby on Rails and Elixir’s Phoenix.
  • +
  • Bolero: A framework for building client-side applications in F# using WebAssembly and Blazor.
  • +
  • Fable: A compiler that translates F# code into JavaScript, enabling integration with popular JavaScript ecosystems like React or Node.js.
  • +
  • Elmish: A model-view-update (MVU) architecture for building web UIs in F#, often used with Fable.
  • +
  • SAFE Stack: An end-to-end, functional-first stack for building cloud-ready web applications. It combines technologies like Saturn, Azure, Fable, and Elmish for a type-safe development experience.
  • +
+ +

Data Science

+ +
    +
  • Deedle: A library for data manipulation and exploratory analysis, similar to pandas in Python.
  • +
  • DiffSharp: A library for automatic differentiation and machine learning.
  • +
  • FsLab: A collection of libraries tailored for data science, including visualization and statistical tools.
  • +
+ +

I haven’t played much with any of them at this point yet, so I’ll reserve any +feedback and recommendations for some point in the future.

+ +

Documentation

+ +

The official documentation is pretty good, although I find it kind of weird that +some of it is hosted on Microsoft’s site +and the rest is on https://fsharp.org/ (the site of the F# Software Foundation).

+ +

I really liked the following parts of the documentation:

+ + + +

https://fsharpforfunandprofit.com/ is another good learning resource. (even if it seems a bit dated)

+ +

Dev Tooling

+ +

I’ve played with the F# plugins for several editors:

+ +
    +
  • Emacs (fsharp-mode)
  • +
  • Zed (third-party plugin)
  • +
  • VS Code (Ionide)
  • +
  • Rider (JetBrains’s .NET IDE)
  • +
+ +

Overall, Rider and VS Code provide the most (and the most polished) features, +but the other options were quite usable as well. That’s largely due to the fact +that the F# LSP server fsautocomplete (naming is hard!) is quite robust and +any editor with good LSP support gets a lot of functionality for free.

+ +

Still, I’ll mention that I found the tooling lacking in some regards:

+ +
    +
  • fsharp-mode doesn’t use TreeSitter (yet) and doesn’t seem to be very actively developed (looking at the code - it seems it was derived from caml-mode)
  • +
  • Zed’s support for F# is quite spartan
  • +
  • In VS Code shockingly the expanding and shrinking selection is broken, which is quite odd for what is supposed to be the flagship editor for F#
  • +
+ +

I’m really struggling with VS Code’s keybindings and editing model, so I’ll likely stick with Emacs going forward. Or I’ll finally spend more quality time with neovim!

+ +

It seems that everyone is using the same code formatter (Fantomas), including the F# team, which is great! +The linter story in F# is not as great (seems the only popular linter FSharpLint is abandonware these days), but when your +compiler is so good, you don’t really need a linter as much.

+ +

Oh, well… It seems that Microsoft are not really particularly invested in +supporting the tooling for F#, as pretty much all the major projects in this +space are community-driven.

+ +

Using AI coding agents (e.g. Copilot) with F# worked pretty well, but I didn’t +spend much time on this front.

+ +

In the end of the day any editor will likely do, as long as you’re using LSP.

+ +

Community

+ +

My initial impression of the community is that it’s fairly small, perhaps even +smaller than that of OCaml. The F# Reddit and Discord (the one listed on +Reddit) seem like the most active places for F# conversations. There’s supposed +to be some F# Slack as well, but I couldn’t get an invite for it. (seems the +automated process for issuing those invites has been broken for a while)

+ +

I’m still not sure what’s the role Microsoft plays in the community, as I +haven’t seen much from them overall.

+ +

For a me a small community is not really a problem, as long as the community is +vibrant and active. Also - I’ve noticed I always feel more connected to smaller +communities. Moving from Java to Ruby back in the day felt like night and day as +far as community engagement and sense of belonging go.

+ +

I didn’t find many books and community sites/blogs dedicated to F#, but I didn’t +really expect to in the first place.

+ +

All in all - I don’t feel qualified to comment much on the F# community at this point.

+ +

Use Cases

+ +

Given the depth and breath of .NET - I guess that sky is the limit for you!

+ +

Seems to me that F# will be a particularly good fit for data analysis and manipulation, because +of features like type providers.

+ +

Probably a good fit for backend services and even full-stack apps, although I haven’t really played +with the F# first solutions in this space yet.

+ +

Fable and Elmish make F# a viable option for client-side programming and might offer +another easy way to sneak F# into your day-to-day work.

+ +

Note: Historically, Fable has been used to target JavaScript but since Fable +4, you can also target other languages such as TypeScript, Rust, Python, and +more.

+ +

Here’s how easy it is to transpile an F# codebase into something else:

+ +
# If you want to transpile to JavaScript
+dotnet fable
+
+# If you want to transpile to TypeScript
+dotnet fable --lang typescript
+
+# If you want to transpile to Python
+dotnet fable --lang python
+
+ +

Cool stuff!

+ +

F# vs OCaml

+ +

F# was derived from OCaml, so the two languages share a lot of DNA. Early on +F# made some efforts to support as much of OCaml’s syntax as possible, and it +even allowed the use of .ml and .mli file extensions for F# code. Over time +the languages started to diverge a bit, though.3

+ +

If you ask most people about the pros and cons of F# over OCaml you’ll probably +get the following answers.

+ +

F# Pros

+ +
    +
  • Runs on .NET +
      +
    • Tons of libraries are at disposal
    • +
    +
  • +
  • Backed by Microsoft
  • +
  • Arguably it’s a bit easier to learn by newcomers (especially those who have only experience with OO programming) +
      +
    • The syntax is slightly easier to pick up (I think)
    • +
    • The compiler errors and warnings are “friendlier” (easier to understand)
    • +
    • It’s easier to debug problems (partially related to the previous item)
    • +
    +
  • +
  • Strong support for async programming
  • +
  • Has some cool features, absent in OCaml, like: +
      +
    • Anonymous Records
    • +
    • Active Patterns
    • +
    • Computational expressions
    • +
    • Sequence comprehensions
    • +
    • Type Providers
    • +
    • Units of measure
    • +
    +
  • +
+ +

F# Cons

+ +
    +
  • Runs on .NET +
      +
    • The interop with .NET influenced a lot of language design decisions (e.g. allowing null)
    • +
    +
  • +
  • Backed by Microsoft +
      +
    • Not everyone likes Microsoft
    • +
    • Seems the resources allocated to F# by Microsoft are modest
    • +
    • It’s unclear how committed Microsoft will be to F# in the long run
    • +
    +
  • +
  • Naming conventions: I like snake_case way more than camelCase and PascalCase
  • +
  • Misses some cool OCaml features +
      +
    • First-class modules and functors
    • +
    • GADTs
    • +
    +
  • +
  • Doesn’t have a friendly camel logo
  • +
  • The name F# sounds cool, but is a search and filename nightmare (and you’ll see FSharp quite often in the wild)
  • +
+ +

Both F# and OCaml can also target JavaScript runtimes as well - via Fable on +the F# side and Js_of_ocaml and Melange on the OCaml side. Fable seems like a +more mature solution at a cursory glance, but I haven’t used any of the three +enough to be able to offer an informed opinion.

+ +

In the end of the day both remain two fairly similar robust, yet niche, +languages, which are unlikely to become very popular in the future. I’m guessing +working professionally with F# is more likely to happen for most people, as .NET +is super popular and I can imagine it’d be fairly easy to sneak a bit of F# here +in there in established C# codebases.

+ +

One weird thing I’ve noticed with F# projects is that they still use XML project +manifests, where you have to list the source files manually in the order in +which they should be compiled (to account for the dependencies between them). I +am a bit shocked that the compiler can’t handle the dependencies automatically, +but I guess that’s because in F# there’s not direct mapping between source files +and modules. At any rate - I prefer the OCaml compilation process (and Dune) way +more.

+ +

As my interest in MLs is mostly educational I’m personally leaning towards OCaml, but if I had to build +web services with an ML language I’d probably pick F#. I also have a weird respect for every language +with its own runtime, as this means that it’s unlikely that the runtime will force some compromises +on the language.

+ +

Closing thoughts

+ +

All in all I liked F# way more than I expected to! In a way it reminded me of my +experience with Clojure back in the day in the sense that Clojure was the most +practical Lisp out there when it was released, mostly because of its great +interop with Java.

+ +

I have a feeling that if .NET was portable since day 1 probably ClojureCLR would have become +as popular as Clojure, and likely F# would have developed a bigger community and +broader usage by now. I’m fairly certain I would have never dabbled in .NET again +if it hadn’t been for .NET Core, and I doubt I’m the only one.

+ +

Learning OCaml is definitely not hard, but I think that people interested to learn some ML +might have an easier time with F#. And, as mentioned earlier, you’ll probably have an +easier path “production” with it.

+ +

I think that everyone who has experience with .NET will benefit from learning F#. +Perhaps more importantly - everyone looking to do more with an ML family language +should definitely consider F#, as it’s a great language in its own right, that gives +you access to one of the most powerful programming platforms out there.

+ +

Let’s not forget about Fable, which makes it possible for you leverage +F# in JavaScript, Dart, Rust and Python runtimes!

+ +

So, why F#? Become it’s seriously fun and seriously practical! +Also if your code compiles - it will probably work the way you expect it to.

+ +

That’s all I have for you today. Please, share in the comments what do you love about F#!

+ +

In sane type systems we trust!

+ +
+
    +
  1. +

    I had some C# courses in the university and I wrote my bachelor’s thesis in C#. It was a rewrite of Arch Linux’s pacman, running on Mono. This was way back in 2007. 

    +
  2. +
  3. +

    See https://fsharp.org/history/hopl-final/hopl-fsharp.pdf 

    +
  4. +
  5. +

    https://github.com/fsharp/fslang-suggestions/issues/985 

    +
  6. +
+
diff --git a/data/planet/cwn/ocaml-weekly-news-01-apr-2025.md b/data/planet/cwn/ocaml-weekly-news-01-apr-2025.md new file mode 100644 index 0000000000..e5c4340c87 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-01-apr-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 01 Apr 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.04.01.html +date: 2025-04-01T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. MlFront_ZipFile - High-level API for zip files
  2. MlFront_Cache - Transient caches + slowly varying data
  3. New lesson on polymorphic variants
  4. The OBazl Toolsuite 3.0.0.beta.1
  5. Dune dev meeting
  6. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-04-feb-2025.md b/data/planet/cwn/ocaml-weekly-news-04-feb-2025.md new file mode 100644 index 0000000000..702b8e75e2 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-04-feb-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 04 Feb 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.02.04.html +date: 2025-02-04T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Opam repository archive - clarification of the opam fields
  2. Chúc mừng năm mới Ất Tỵ 2025!
  3. Rewriting Slipshow in OCaml: The undo-able monad
  4. Announcing climate.0.4.0
  5. 15th MirageOS retreat May 13th - 20th
  6. Dune dev meeting
  7. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-04-mar-2025.md b/data/planet/cwn/ocaml-weekly-news-04-mar-2025.md new file mode 100644 index 0000000000..973d516f6b --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-04-mar-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 04 Mar 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.03.04.html +date: 2025-03-04T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Bytecode debugging in OCaml 5.3
  2. Zanuda -- OCaml linter experiment
  3. QCheck 0.24
  4. Bogue, the OCaml GUI
  5. Opam repository archival - next phase
  6. Upcoming Cmdliner 2.0 changes that need your attention
  7. OCaml Editors Plugins Survey
  8. Dune dev meeting
  9. Platform Newsletter: September - December 2024
  10. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-06-may-2025.md b/data/planet/cwn/ocaml-weekly-news-06-may-2025.md new file mode 100644 index 0000000000..5fd1821478 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-06-may-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 06 May 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.05.06.html +date: 2025-05-06T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Docfd 11.0.0: TUI multiline fuzzy document finder
  2. opam 2.4.0~alpha1
  3. Early work experimenting with zig as a cross-compiler for OCaml
  4. Dune 3.18
  5. A tool to reverse debug OCaml/other binary runs
  6. opam 2.4.0~alpha2
  7. (BER) MetaOCaml N153, for OCaml 5.3.0
  8. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-07-jan-2025.md b/data/planet/cwn/ocaml-weekly-news-07-jan-2025.md new file mode 100644 index 0000000000..642de918e7 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-07-jan-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 07 Jan 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.01.07.html +date: 2025-01-07T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Playing with Windows on ARM64
  2. Opam repository archival, Phase 1: unavailable packages
  3. CCL: Categorical Configuration Language
  4. Dune dev meeting
  5. "Cram tests: a hidden gem of dune" and "Snapshot tests for your own ppx"
  6. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-08-apr-2025.md b/data/planet/cwn/ocaml-weekly-news-08-apr-2025.md new file mode 100644 index 0000000000..7afc0552ce --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-08-apr-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 08 Apr 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.04.08.html +date: 2025-04-08T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Ocsigen public meeting
  2. Roguetype
  3. Ppx_untype: An end to type errors in OCaml
  4. Second of Two Lessons on Polymorphic Variants: Practical Usecases
  5. Caqti 2.2.4 Release and Plans
  6. update for the magick-core-7
  7. gegl-0.4 _
  8. Dune 3.18
  9. QCheck 0.24
  10. checked_oint v0.5.0: Safe integer arithmetic for OCaml
  11. Outreachy December 2024 Round
  12. OUPS meetup april 2025
  13. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-11-feb-2025.md b/data/planet/cwn/ocaml-weekly-news-11-feb-2025.md new file mode 100644 index 0000000000..e162c75e46 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-11-feb-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 11 Feb 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.02.11.html +date: 2025-02-11T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. ocamlmig, a tool to rewrite ocaml code, and complement ~[@@deprecated]~
  2. Mopsa 1.1 -- Modular Open Platform for Static Analysis
  3. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-11-mar-2025.md b/data/planet/cwn/ocaml-weekly-news-11-mar-2025.md new file mode 100644 index 0000000000..a76c7fc460 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-11-mar-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 11 Mar 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.03.11.html +date: 2025-03-11T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. OCaml projects utilizing Category theory
  2. Docker base images and OCaml-CI support for OCaml lt 4.08
  3. ocamlmig, a tool to rewrite ocaml code, and complement ~[@@deprecated]~
  4. Ortac 0.6.0 improve bug reporting
  5. Dune Developer Preview Updates
  6. ppxlib.0.36.0
  7. I created an OCaml grammar for ANTLR4 (Earley parser compatible)
  8. Melange 5.0
  9. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-14-jan-2025.md b/data/planet/cwn/ocaml-weekly-news-14-jan-2025.md new file mode 100644 index 0000000000..a05c1994a2 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-14-jan-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 14 Jan 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.01.14.html +date: 2025-01-14T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. On concurrency models
  2. OCaml 5.3.0 released
  3. dream-html and pure-html 3.9.5
  4. Building an OCaml cross compiler with OCaml 5.3
  5. Ppx deriving decoders
  6. Ortac 0.5.0 testing higher order functions
  7. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-15-apr-2025.md b/data/planet/cwn/ocaml-weekly-news-15-apr-2025.md new file mode 100644 index 0000000000..dc707ed3d8 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-15-apr-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 15 Apr 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.04.15.html +date: 2025-04-15T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Semgrep is hiring OCaml developers to help develop our supply chain security product!
  2. Subprocess: a library for launching and communicating with Unix commands
  3. cudajit: Bindings to the ~cuda~ and ~nvrtc~ libraries
  4. qcheck-lin and qcheck-stm 0.2
  5. Call for Volunteers to Help Maintain the Opam-Repository
  6. Dune package management update
  7. Ocsigen public meeting
  8. Looking for Maintainers / Moderators for the OCaml Cookbook
  9. SCGI library for OCaml and eio
  10. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-18-feb-2025.md b/data/planet/cwn/ocaml-weekly-news-18-feb-2025.md new file mode 100644 index 0000000000..1aba1b841f --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-18-feb-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 18 Feb 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.02.18.html +date: 2025-02-18T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Learn Programming with OCaml (new book)
  2. Ocsigen's 2024 recap
  3. OCaml GADTs for Authentication Tokens
  4. OCaml language committe launched
  5. Dune dev meeting
  6. Asking For Community Feedback on the OCaml Platform Communications
diff --git a/data/planet/cwn/ocaml-weekly-news-18-mar-2025.md b/data/planet/cwn/ocaml-weekly-news-18-mar-2025.md new file mode 100644 index 0000000000..2b19e69cae --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-18-mar-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 18 Mar 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.03.18.html +date: 2025-03-18T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Upgrading Semgrep from OCaml 4 to OCaml 5 + dynamic_gc utility
  2. Open source OCaml algotrading with longleaf 1.0.0
  3. Neocaml - a TreeSitter-powered Emacs package for OCaml programming
  4. Senior Software Engineer at Bloomberg. New York
  5. Upcoming Cmdliner 2.0 changes that need your attention
  6. Dune dev meeting
  7. New release of Monolith (20250314)
  8. dream_middleware_ext v0.1.0
  9. Learn Programming with OCaml (new book)
  10. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-21-jan-2025.md b/data/planet/cwn/ocaml-weekly-news-21-jan-2025.md new file mode 100644 index 0000000000..9a78291635 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-21-jan-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 21 Jan 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.01.21.html +date: 2025-01-21T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. OCaml Software Foundation: January 2025 update
  2. ppxlib.034.0
  3. Release of Carton 1.0.0 and Cachet
  4. Opam repository archival, phase 2 - OCaml 4.08 is the lower bound
  5. Ocaml-posix 2.1.0 released!
  6. Release of ocaml-eglot 1.0.0
  7. Semgrep is hiring to help scale their static analysis engine
  8. Dune dev meeting
  9. Tarides: 2024 in Review
  10. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-22-apr-2025.md b/data/planet/cwn/ocaml-weekly-news-22-apr-2025.md new file mode 100644 index 0000000000..f217c42260 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-22-apr-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 22 Apr 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.04.22.html +date: 2025-04-22T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Flambda2 Ep. 4: How to write a purely functional compiler, by OCamlPro
  2. R and D Engineer Positions available at OCamlPro, in Paris (France)
  3. Release of ocaml-eglot 1.2.0
  4. Outreachy December 2024 Round
  5. Dune 3.18
  6. opam 2.4.0~alpha1
  7. ML Family Workshop 2025: Call for Presentations
  8. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-25-feb-2025.md b/data/planet/cwn/ocaml-weekly-news-25-feb-2025.md new file mode 100644 index 0000000000..25559f5308 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-25-feb-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 25 Feb 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.02.25.html +date: 2025-02-25T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Early work experimenting with zig as a cross-compiler for OCaml
  2. Dune dev meeting
  3. Outreachy June 2025
  4. Js_of_ocaml 6.0.1 / Wasm_of_ocaml
  5. Bytecode debugging in OCaml 5.3
  6. New F* release on opam (2025.02.17)
  7. Other OCaml News
diff --git a/data/planet/cwn/ocaml-weekly-news-25-mar-2025.md b/data/planet/cwn/ocaml-weekly-news-25-mar-2025.md new file mode 100644 index 0000000000..9d23093851 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-25-mar-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 25 Mar 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.03.25.html +date: 2025-03-25T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Ocsigen migrating to effect-based concurrency
  2. Slipshow!
  3. Odoc 3.0 released!
  4. 4th editor tooling dev-meeting: 28th of March
  5. The Call for Papers for FUNARCH2025 is open!
  6. Proposal for the replacement of Set and Map in the stdlib
  7. A tool to reverse debug OCaml (and other binaries) runs
  8. Feedback request: New lesson on ~Lazy~
  9. OCaml Workshop 2025 at ICFP/SPLASH - announcement and call for proposals
diff --git a/data/planet/cwn/ocaml-weekly-news-28-jan-2025.md b/data/planet/cwn/ocaml-weekly-news-28-jan-2025.md new file mode 100644 index 0000000000..5f30ae5a01 --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-28-jan-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 28 Jan 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.01.28.html +date: 2025-01-28T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. Google Summer of Code
  2. Merlin and OCaml-LSP support experimental project-wide renaming
  3. qcheck-lin and qcheck-stm 0.2
  4. Dune 3.17
  5. Odoc 3 Beta Release
  6. 2024 at OCamlPro
diff --git a/data/planet/cwn/ocaml-weekly-news-29-apr-2025.md b/data/planet/cwn/ocaml-weekly-news-29-apr-2025.md new file mode 100644 index 0000000000..bbd2a67b8d --- /dev/null +++ b/data/planet/cwn/ocaml-weekly-news-29-apr-2025.md @@ -0,0 +1,12 @@ +--- +title: OCaml Weekly News, 29 Apr 2025 +description: +url: https://alan.petitepomme.net/cwn/2025.04.29.html +date: 2025-04-29T12:00:00-00:00 +preview_image: +authors: +- Caml Weekly News +source: +--- + +
  1. dream-html, pure-html 3.10.0 and 3.10.1
  2. State of OCaml Platform on Windows
  3. Upgrading Semgrep from OCaml 4 to OCaml 5 + dynamic_gc utility
  4. Typesafe complicated combinations
  5. Other OCaml News
diff --git a/data/planet/dinosaure/bstr-a-synthetic-library-for-bigstrings.md b/data/planet/dinosaure/bstr-a-synthetic-library-for-bigstrings.md new file mode 100644 index 0000000000..de533d5372 --- /dev/null +++ b/data/planet/dinosaure/bstr-a-synthetic-library-for-bigstrings.md @@ -0,0 +1,12 @@ +--- +title: Bstr, a synthetic library for bigstrings +description: +url: https://blog.osau.re/articles/bstr.html +date: 2025-04-29T00:00:00-00:00 +preview_image: +authors: +- Romain Calascibetta +source: +--- + +A small library to manipulate bstr diff --git a/data/planet/gallium/florian-compiler-weekly-11-december-2023.md b/data/planet/gallium/florian-compiler-weekly-11-december-2023.md index 64a471d78c..56841d9aaf 100644 --- a/data/planet/gallium/florian-compiler-weekly-11-december-2023.md +++ b/data/planet/gallium/florian-compiler-weekly-11-december-2023.md @@ -17,9 +17,9 @@ release of OCaml 5.1.1, some review work on occurrences analysis for OCaml projects and a bit of on-going work on structured logs.

- - + +

OCaml 5.1.1

OCaml 5.1.0 has been released nearly three months ago, in those months we have discovered a few significant bugs that were impeding the @@ -179,7 +179,7 @@ increase to a less dramatic factor 6.

experimental runtime. And while waiting for a better solution, the collection of bug fixes integrated in OCaml 5.1.1 should made it possible to use numerical code in OCaml.

-

Project-wide occurence index

+

Project-wide occurrence index

Beyond the release of OCaml 5.1.1, I have been working on reviewing PRs.

With Gabriel Scherer and Ulysse Gérard, we spend an afternoon reading @@ -248,6 +248,3 @@ identifiers are as fresh as we need them to be:

module New_record(Root:Def)(): Record with type root := Root.id module New_sum(Root:Def)(): Sum with type root := Root.id - - - diff --git a/data/planet/gallium/florians-compiler-weekly-13-january-2025.md b/data/planet/gallium/florians-compiler-weekly-13-january-2025.md new file mode 100644 index 0000000000..4423073914 --- /dev/null +++ b/data/planet/gallium/florians-compiler-weekly-13-january-2025.md @@ -0,0 +1,369 @@ +--- +title: "Florian\u2019s compiler weekly, 13 January 2025" +description: +url: https://gallium.inria.fr/blog/florian-cw-2025-01-13 +date: 2025-01-13T08:00:00-00:00 +preview_image: +authors: +- GaGallium +source: +--- + + + +

This series of blog post aims to give a short weekly glimpse into my +(Florian Angeletti) work on the OCaml compiler. This week subject is my +personal retrospective on the release of OCaml 5.3.0.

+ + + + + +

The beginning of 2025 and the release of OCaml 5.3 feels like a good +period for some introspection on my work on the compiler during this +release.

+

Looking backk at the changelog, I have participated to more or less +50 changes in the 5.3 release. Most of those changes (~40) can be +classified into five major themes:

+
    +
  • Error messages
  • +
  • Compiler display infrastructure
  • +
  • Tooling integration
  • +
  • Manual and documentation
  • +
  • Type system bug fixes
  • +
+

Retrospecting, I have been quite busy this release with background +work, and I still have more background work planned for OCaml 5.4. +Hopefully, this background work will bear more visible fruits in the +next releases.

+

Error messages

+

The first theme for this release is recurrent for me, and I hope that +I would be able to spend even more time on this subject soon. Indeed for +this release, most of the error message improvements were relatively +quick improvements on various topics (first class modules, function +labelled arguments, functors and type clashes). Nevertheless, I still +have many larger projects planned for improving error messages in the +longer terms, in particular:

+
    +
  • Efficient diffing for module level error messages: there is +prototype implementation written by Malo Monin on his summer internship +last summer which needs more polish before being integrated.
  • +
  • Semantic diffing on type expressions: using the more reliable error +trace, I hope to come back to my previous on syntaxic difference +highlighting in type expressions and implement a fully semantic +version.
  • +
+

For more details, here are the corresponding changelog entries +extracted from the 5.3 changelog:

+
    +
  • #12980: +Explain type mismatch involving first-class modules by including the +module level error message (Florian Angeletti, review by Vincent +Laviron)

  • +
  • #12985, +#12988: Better +error messages for partially applied functors. (Florian Angeletti, +report by Arthur Wendling, review by Gabriel Scherer)

  • +
  • #13034, +#13260: Better +error messages for mismatched function labels (Florian Angeletti, report +by Daniel Bünzli, review by Gabriel Scherer and Samuel Vivien)

  • +
  • #13341: +a warning when the pattern-matching compiler pessimizes code because +side-effects may mutate the scrutinee during matching. (This warning is +disabled by default, as this rarely happens and its performance impact +is typically not noticeable.) (Gabriel Scherer, review by Nick Roberts, +Florian Angeletti and David Allsopp)

  • +
  • #13255: +Re-enable warning 34 for unused locally abstract types (Nick Roberts, +review by Chris Casinghino and Florian Angeletti)

  • +
  • #12182: +Improve the type clash error message. For example, this message: This +expression has type … is changed into: The constant “42” has type … +(Jules Aguillon, review by Gabriel Scherer and Florian +Angeletti)

  • +
  • #13170: +Fix a bug that would result in some floating alerts +[@@@alert ...] incorrectly triggering Warning 53. (Nicolás +Ojeda Bär, review by Chris Casinghino and Florian Angeletti)

  • +
  • #13203: +Do not issue warning 53 if the compiler is stopping before attributes +have been accurately marked. (Chris Casinghino, review by Florian +Angeletti)

  • +
+

Compiler display +infrastructure

+

This release I ended up spending a sizeable amount of time +refactoring or improving the various display mechanism in the compiler. +In particular, OCaml 5.3 comes with a new internal format for error +messages, a new graphical debugger printer for type expressions, and the +correction on many smaller printing bugs for booleans and the +mod operator.

+

This trend will continue in OCaml 5.4 since I have already launched a +project on updating the formatting of error messages and warnings, and I +am hoping to finally integrate my work on structured diagnostics in this +version of OCaml.

+

However, beyond this (significant) piece of work, don’t really have +longer plans on this subject.

+

The related changelog entries for OCaml 5.3 are:

+

Highlights

+
    +
  • #13049: +graphical debugging printer for types (Florian Angeletti, review by +Gabriel Scherer)

  • +
  • #13169, +#13311: +Introduce a document data type for compiler messages rather than relying +on Format.formatter -> unit closures. (Florian +Angeletti, review by Gabriel Scherer)

  • +
+

Error messages styling

+
    +
  • #12891: +Improved styling for initial prompt (Florian Angeletti, review by +Gabriel Scherer)

  • +
  • #13263, +#13560: fix +printing true and false in toplevel and error messages (no more +unexpected #true) (Florian Angeletti, report by Samuel Vivien, review by +Gabriel Scherer)

  • +
  • #13151, +name conflicts explanation as a footnote (Florian Angeletti, review by +Gabriel Scherer)

  • +
  • #13053: +Improved display of builtin types such as _ list when +aliased. (Samuel Vivien, review by Florian Angeletti)

  • +
+

Internal refactoring and bug +fixes

+
    +
  • #13336: +compiler-libs, split the Printtyp in three to only keep +“user-friendly” functions in the Printtyp module. (Florian +Angeletti, review by Gabriel Scherer)

  • +
  • #12888: +fix printing of uncaught exceptions in .cmo files passed on +the command-line of the toplevel. (Nicolás Ojeda Bär, review by Florian +Angeletti, report by Daniel Bünzli)

  • +
  • #13099: +Fix erroneous loading of cmis for some module type errors. (Nick +Roberts, review by Florian Angeletti)

  • +
  • #13251: +Register printer for errors in Emitaux (Vincent Laviron, review by Miod +Vallat and Florian Angeletti)

  • +
+

Source printer

+
    +
  • #13391, +#13551: fix a +printing bug with -dsource when using raw literal inside a +locally abstract type constraint +(i.e. let f: type \#for. ...) (Florian Angeletti, report by +Nick Roberts, review by Richard Eisenberg)

  • +
  • #13603, +#13604: fix +source printing in the presence of the escaped raw identifier +\#mod. (Florian Angeletti, report by Chris Casinghino, +review by Gabriel Scherer)

  • +
+

Tooling integration

+

Another important subject during this release was the improvement of +the metadata generated for Merlin. OCaml 5.3.0 metadata now track more +accurately identifiers across implementation and interfaces, and record +precisely how implementation identifiers were matched to interface +identifiers in a module. For the next release, I am planning on +improving tooling integration with merlin by reducing the difference +between merlin typechecker and the compiler typechecker. The exact +specification can be found following the link in the corresponding +changelog entry:

+
    +
  • #13308: +keep track of relations between declaration in the cmt files. This is +useful information for external tools for navigation and analysis +purposis. (Ulysse Gérard, Florian Angeletti, review by Florian Angeletti +and Gabriel Scherer)

  • +
  • #13286: +Distinguish unique identifiers Shape.Uid.t according to +their provenance: either an implementation or an interface. (Ulysse +Gérard, review by Florian Angeletti and Leo White)

  • +
+

In a similar way, I have also worked on improving the compatibility +of the internal compiler library with ppxlib and MetaOCaml, and +implemented a new command line flag to improve the backward +compatibility of the lexer:

+
    +
  • #11129, +#11148: +enforce that ppxs do not produce parsetrees with an empty +list of universally quantified type variables +(. int -> int instead of +'a . int -> int') (Florian Angeletti, report by Simmo +Saan, review by Gabriel Scherer)

  • +
  • #13471: +add -keywords <version?+list> flag to define the list +of keywords recognized by the lexer, for instance +-keywords 5.2 disable the effect keyword. +(Florian Angeletti, review by Gabriel Scherer)

  • +
  • #13257: +integrate MetaOCaml in the Menhir grammar to ease MetaOCaml maintenance. +This is a purely internal change: there is no support in the lexer, so +no change to the surface OCaml grammar. (Oleg Kiselyov, Gabriel Scherer +and Florian Angeletti, review by Jeremy Yallop)

  • +
+

Manual and documentation:

+

As an author, I have documented the modest Unicode support introduced +in 5.3 and found the time to write down the compiler release cycles. +However, most on my time working on the documentation has been focused +on reviewing PRs, ranging from a small change to the manual css to an +update to the manual section on polymorphic recursion proposed by a new +contributor.

+
    +
  • #13668: +Document the basic support for unicode identifiers and the switch to +UTF-8 encoded Unicode text for OCaml source file (Florian Angeletti, +review by Nicolás Ojeda Bär and Daniel Bünzli)

  • +
  • #12949: +document OCaml release cycles and version strings in +release-info/introduction.md. (Florian Angeletti, review by +Fabrice Buoro, Kate Deplaix, Damien Doligez, and Gabriel +Scherer)

  • +
  • #12298: +Manual: emphasize that Bigarray.int refers to an OCaml integer, which +does not match the C int type. (Edwin Török, review by Florian +Angeletti)

  • +
  • #12868: +Manual: simplify style colours of the post-processed manual and API HTML +pages, and fix the search button icon (Yawar Amin, review by Simon +Grondin, Gabriel Scherer, and Florian Angeletti)

  • +
  • #12976: +Manual: use webman/version/ * .htmlandwebman/version/api/ +for OCaml.org HTML manual generation (Shakthi Kannan, review by Hannes +Mehnert, and Florian Angeletti)

  • +
  • #13295: +Use syntax for deep effect handlers in the effect handlers manual page. +(KC Sivaramakrishnan, review by Anil Madhavapeddy, Florian Angeletti and +Miod Vallat)

  • +
  • #13469, +#13474, #13535: Document +that [Hashtbl.create n] creates a hash table with a default minimal +size, even if [n] is very small or negative. (Antonin Décimo, Nick +Bares, report by Nikolaus Huber and Jan Midtgaard, review by Florian +Angeletti, Anil Madhavapeddy, Gabriel Scherer, and Miod Vallat)

  • +
  • #13666: +Rewrite parts of the example code around nested lists in Chapter 6 +(Polymorphism and its limitations -> Polymorphic recursion) giving +the “depth” function [in the non-polymorphically-recursive part of the +example] a much more sensible behavior; also fix a typo and some +formatting. (Frank Steffahn, review by Florian Angeletti)

  • +
+

Type system bug fixes

+

At last, but not least, I spent many hours this release fixing +internal errors due to inconsistent type constraints in the module +systems. I have also reviewed many bug fixes and in particular a serie +of issues in the typechecker related to the handling of non-injective +type parameters.

+
    +
  • #12959, +#13055: Avoid +an internal error on recursive module type inconsistency (Florian +Angeletti, review by Jacques Garrigue and Gabriel Scherer)

  • +
  • #13388, +#13540: raises +an error message (and not an internal compiler error) when two local +substitutions are incompatible (for instance +module type S:=sig end type t:=(module S)) (Florian +Angeletti, report by Nailen Matschke, review by Gabriel Scherer, and Leo +White)

  • +
  • #13185, +#13192: Reject +type-level module aliases on functor parameter inside signatures. +(Jacques Garrigue, report by Richard Eisenberg, review by Florian +Angeletti)

  • +
  • #13306: +An algorithm in the type-checker that checks two types for equality +could sometimes, in theory, return the wrong answer. This patch fixes +the oversight. No known program triggers the bug. (Richard Eisenberg, +review by Florian Angeletti)

  • +
  • #13495, +#13514: Fix +typechecker crash while typing objects (Jacques Garrigue, report by +Nicolás Ojeda Bär, review by Nicolas Ojeda Bär, Gabriel Scherer, Stephen +Dolan, Florian Angeletti)

  • +
  • #13579, +#13583: +Unsoundness involving non-injective types + gadts (Jacques Garrigue, +report by @v-gb, review +by Richard Eisenberg and Florian Angeletti)

  • +
  • #13598: +Falsely triggered warning 56 [unreachable-case] This was caused by +unproper protection of the retyping function. (Jacques Garrigue, report +by Tõivo Leedjärv, review by Florian Angeletti)

  • +
+

Miscellaneous

+

Beyond those major themes, I also had my hands or eyes at few of the +changes in the language, the standard library and the compiler build +system.

+

Language features:

+

In term of language features, I partipated to the review for the +newly introduced syntax for effect handler (#12309, #13158) on the +type system and documentation (#13295) +sides.

+
let with_gen f = match f () with
+| effect Random_float, k -> Effect.Deep.continue k (Random.float 1.)
+| x -> x
+

I also finalized the support the new modest support of utf-8 encoded +Unicode source files in OCaml 5.3 (#11736, #12664, #13628)

+
type saison = Printemps | Été | Automne | Hiver
+

and documented it (#13668).

+

Type system

+

On the pure type system side, I have participated to the review on +the extended support for annotating types in GADT pattern. (#11891, #12507). It is +now possible to give a name to all type variables introduced by pattern +matching on a GADT constructor

+
type _ t =
+| S: string -> char array t
+| A: 'a array -> 'a array t
+
+let len (type a) (x:a t) = match x with
+| A (type a) (x:a array) -> Array.length x
+| S x -> String.length x
+

whereas it was only possible to name existentially quantified type +variables before.

+

Standard library:

+

I have reviewed two standard library Pull Requests (PR)

+
    +
  • #13168: +In Array.shuffle, clarify the code that validates the result of the +user-supplied function rand, and improve the error message +that is produced when this result is invalid. (François Pottier, review +by Florian Angeletti, Daniel Bünzli and Gabriel Scherer)

  • +
  • #13296: +Add mem, memq, find_opt, find_index, find_map and find_mapi to Dynarray. +(Jake H, review by Gabriel Scherer and Florian Angeletti)

  • +
+

and authored one PR exposing support for a hidden feature of the +Format module:

+
    +
  • #12133: +Expose support for printing substrings in Format (Florian Angeletti, +review by Daniel Bünzli, Gabriel Scherer and Nicolás Ojeda Bär)
  • +
+

Build system:

+

During the release, I also happened to review some build system +changes:

+
    +
  • #13285: +continue the merge of the sub-makefiles into the root Makefile started +with #11243, +#11248, #11268, #11420, #11675, #12198, #12321, #12586, #12616, #12706 and #13048. +(Sébastien Hinderer, review by David Allsopp and Florian +Angeletti)

  • +
  • (breaking change) #13070: On +Windows, when configured with bootstrapped flexdll, don’t add +flexdll +to the search path when -nostdlib is specified (which then means +-L path-to-flexdll no longer gets passed to the system +linker). (David Allsopp, review by Florian Angeletti)

  • +
+ + + diff --git a/data/planet/janestreet/advent-of-hardcaml.md b/data/planet/janestreet/advent-of-hardcaml.md new file mode 100644 index 0000000000..4466607334 --- /dev/null +++ b/data/planet/janestreet/advent-of-hardcaml.md @@ -0,0 +1,19 @@ +--- +title: Advent of Hardcaml +description: Advent of Code is an annual Advent calendarfeaturing small programming + puzzles created by Eric Wastl, which has been runningevery December since 2015. + Being ... +url: https://blog.janestreet.com/advent-of-hardcaml-2024/ +date: 2025-03-22T00:00:00-00:00 +preview_image: https://blog.janestreet.com/advent-of-hardcaml-2024/snowglobe_camel.png +authors: +- Jane Street Tech Blog +source: +--- + +

Advent of Code is an annual Advent calendar +featuring small programming puzzles created by Eric Wastl, which has been running +every December since 2015. Being the puzzle-lovers we are, a bunch of us at +Jane Street participate in Advent of Code every year.

+ + diff --git a/data/planet/janestreet/how-we-accidentally-built-a-better-build-system-for-ocaml.md b/data/planet/janestreet/how-we-accidentally-built-a-better-build-system-for-ocaml.md new file mode 100644 index 0000000000..483076d5bc --- /dev/null +++ b/data/planet/janestreet/how-we-accidentally-built-a-better-build-system-for-ocaml.md @@ -0,0 +1,20 @@ +--- +title: How we accidentally built a better build system for OCaml +description: "A \u201Cbuild system\u201D is one of the most important tools in a developer\u2019stoolbox. + Roughly, it figures out how to create runnable programs froma bunch of different..." +url: https://blog.janestreet.com/how-we-accidentally-built-a-better-build-system-for-ocaml-index/ +date: 2025-01-24T00:00:00-00:00 +preview_image: https://blog.janestreet.com/how-we-accidentally-built-a-better-build-system-for-ocaml-index/dune-jenga.png +authors: +- Jane Street Tech Blog +source: +--- + +

A “build system” is one of the most important tools in a developer’s +toolbox. Roughly, it figures out how to create runnable programs from +a bunch of different source files by calling out to the compiler, +setting up and executing test suites, and so on. Because you interact +with it daily, above all it has to be fast – +but it also has to be flexible.

+ + diff --git a/data/planet/melange/announcing-melange-5.md b/data/planet/melange/announcing-melange-5.md new file mode 100644 index 0000000000..7fa96573eb --- /dev/null +++ b/data/planet/melange/announcing-melange-5.md @@ -0,0 +1,217 @@ +--- +title: Announcing Melange 5 +description: +url: https://melange.re/blog/posts/announcing-melange-5 +date: 2025-03-05T00:00:00-00:00 +preview_image: +authors: +- Melange Blog +source: +--- + +

We are excited to announce the release of Melange 5, the compiler for OCaml +that targets JavaScript.

+

A lot of goodies went into this release! While our focus was mostly on features +that make it easy to express more JavaScript constructs and supporting OCaml +5.3, we also managed to fit additional improvements in the release: better +editor support for Melange externals, code generation improvements, and +better compiler output for generated JS. The most notable feature we're +shipping in Melange 5 is support for JavaScript's dynamic +import(), +which we'll describe in detail below.

+

Read on for the highlights.

+
+

Dynamic import() without sacrificing type safety

+

Support for JavaScript's dynamic import() is probably what I'm most excited +about in this Melange release. In Melange 5, we're releasing support for +JavaScript's import() via a new function in melange.js, Js.import: 'a -> 'a promise. I gave a small preview of dynamic import() during my Melange +talk at Fun OCaml +2024.

+

Js.import is type-safe and build system-compatible. Let's break it +down:

+
    +
  1. build system-compatible: dynamic import()s in Melange work with Dune +out of the box: as usual, you must specify your (library ..) dependencies +in the dune file. At compile time, Melange will be aware of the +dynamically imported module locations to emit the arguments to +import("/path/to/module.js) automatically.
  2. +
  3. type-safe: your OCaml code is still aware of its dependencies at +compile-time, but Melange will skip emitting static JavaScript import .. +declarations if the values are exclusively used through Js.import(..).
  4. +
+

Dynamically importing OCaml code

+

The example below makes it clear: we import the entire Stdlib.Int module, +specify its type signature, and observe that no static imports appear in the +resulting JavaScript:

+
js
// dynamic_import_int.re
+
+module type int = (module type of Int);
+
+let _: Js.Promise.t(unit) = {
+  Js.import((module Stdlib.Int): (module int))
+  |> Js.Promise.then_((module Int: int) =>
+      Js.Promise.resolve(Js.log(Int.max))
+  );
+};
+
js
// dynamic_import_int.js
+
+import("melange/int.js").then(function (Int) {
+  return Promise.resolve((console.log(Int.max), undefined));
+});
+

Dynamically importing JavaScript from OCaml

+

One of Melange's primary operating principles is the ability to support +seamless interop with JavaScript constructs. As such, we implemented import() +in a way that also allows importing JS modules dynamically: you can call +Js.import on JavaScript values declared with external. The abstractions +compose nicely to produce the expected result. Check out this example of +dynamically importing React.useEffect:

+
js
// dynamically_imported_useEffect.re
+
+[@mel.module "react"]
+external useEffect:
+([@mel.uncurry] (unit => option(unit => unit))) => unit = "useEffect";
+
+let dynamicallyImportedUseEffect = Js.import(useEffect);
+

And the JS output:

+
js
// dynamically_imported_useEffect.js
+
+const dynamicallyImportedUseEffect = import("react").then(function (m) {
+  return m.useEffect;
+});
+
+export {
+  dynamicallyImportedUseEffect,
+}
+

Discriminated unions support: @mel.as in variants

+

This release of Melange includes a major feature that improves the compilation +of variants, including really good support for representing discriminated +unions, +a common pattern to represent polymorphic objects with a discriminator in +JavaScript/TypeScript.

+

In melange-re/melange#1189, +we introduced support for 2 attributes in OCaml types that define variants:

+

@mel.as

+

Specifying [@mel.as ".."] changes the variant emission in JavaScript to that +string value.

+
js
type t =
+  | [@mel.as "World"] Hello;
+
+let t = Hello
+
js
const t = /* Hello */ "World";
+

@mel.tag

+

A @mel.as variant type combined with @mel.tag allows expressing +discriminated unions in an unobtrusive way:

+
js
[@mel.tag "kind"]
+type t =
+  | [@mel.as "Foo"] Foo({ a: string, b: string, })
+  | [@mel.as "Bar"] Bar({ c: string, d: string, });
+
+let x = Foo({ a: "a", b: "b", });
+
+let y = Bar({ c: "c", d: "d", });
+

The Reason code above produces the following JavaScript:

+
js
const x = {
+  kind: /* Foo */ "Foo",
+  a: "a",
+  b: "b"
+};
+
+const y = {
+  kind: /* Bar */ "Bar",
+  c: "c",
+  d: "d"
+};
+

In summary:

+
    +
  • [@mel.tag "kind"] specifies that each variant containing a payload should +be tagged with "kind".
  • +
  • the [@mel.as ".."] attribute in each variant type specifies what that +payload should be for each branch of the variant type.
  • +
+

@mel.send is way, way better

+

When binding to methods of an object in JavaScript, Melange has historically +supported 2 different ways of achieving the same: @mel.send and +@mel.send.pipe. The only real reason why 2 constructs existed to do the same +was to support two alternatives for chaining them in OCaml: +pipe-first and +pipe-last. But +this always felt like an afterthought, and code using @mel.send.pipe never +felt intuitive to look at (e.g. in external say: unit [@mel.send.pipe: t], +one had to mentally place the t before unit, since the real signature is t -> unit).

+

In Melange 5, we wanted to remove this weird split and further reduce the +cognitive overhead of writing bindings to call JavaScript methods on an object +or instance.

+

We're introducing a way to mark the "self" instance argument with +@mel.this and recommending only the use of @mel.send going forward. +Starting from this release, @mel.send.pipe has been deprecated, and will be +removed in the next major release of Melange. Here's an example:

+
js
[@mel.send]
+external push: (~value: 'a=?, [@mel.this] array('a)) => unit = "push";
+
+let () = push([||], ~value=3);
+

The code above marks the array('a) argument as the instance to call the +push method, which produces the following JavaScript:

+
js
[].push(3);
+

Besides being more versatile, having an explicit marker with @mel.this is +also more visually intuitive: when scanning Melange code containing external +bindings, it becomes easier to spot which is the "this" argument. This feature +is fully backwards compatible with @mel.send: in the absence of @mel.this, +the instance argument defaults to the first one declared in the signature, as +previously supported.

+

Additional quality of life improvements

+

OCaml 5.3 Compatibility / Stdlib Upgrade

+

Since Melange's +inception, one +of its goals has been to keep it up to date with the latest OCaml releases. +This +release +brings Melange up to speed with OCaml 5.3, including upgrades to the Stdlib +library as well. We're also releasing Melange 5 for OCaml +4.14, +5.1 +and +5.2.

+

Melange runtime NPM packages

+

Starting from this release, we're shipping NPM packages with the precompiled +Melange runtime. This feature, requested by a few users in +melange#620 allows to use +Melange without compiling its own runtime and stdlib (essentially, in +combination with (emit_stdlib false) in (melange.emit ..)).

+

This can be useful in monorepos that compile multiple Melange applications but, +perhaps most importantly, it enables Melange libraries and packages to also +be published in NPM without the weight of the full runtime / stdlib.

+

Better editor support for Melange externals

+

Melange bindings to JavaScript, specified through external declarations, used +to propagate internal information in the native +payload. In +practice, hovering over one of these in your editor could end up looking a bit +weird:

+

+

Since +melange-re/melange#1222, +Melange now propagates this information via internal attributes that only the +Melange compiler recognizes. These don't show up when hovering over +declarations in editors, making the resulting output much less jarring to look +at:

+

+

Prettified JavaScript Output

+

In Melange 5, we modernized the JavaScript emitter to produce cleaner, more +readable, and better-indented code. Melange 5 generated JS looks remarkably +closer to hand-written JavaScript, with this release enhancing that quality +even further.

+

Conclusion

+

Melange 5 crosses a major milestone for JavaScript expressivity, bringing great +features like idiomatic dynamic import()s and support for discriminated +unions. Compatibility with OCaml 5.3 marks Melange's commitment to parity with +the latest OCaml versions. In this latest version, Melange raises the bar for +increasingly prettier JavaScript prettification, and the Melange precompiled +runtime starts to be available on NPM.

+

Check out the full +changelog +for detailed information on all the changes that made it into this release. If +you find any issues or have questions, feel free to open an issue on our +GitHub issue tracker.

+

This release was sponsored by the generous support of +Ahrefs and the OCaml Software +Foundation.

+ diff --git a/data/planet/mirage/easy-distributed-analytics-with-irmin-10.md b/data/planet/mirage/easy-distributed-analytics-with-irmin-10.md index d0463d79f7..2ba9ab2066 100644 --- a/data/planet/mirage/easy-distributed-analytics-with-irmin-10.md +++ b/data/planet/mirage/easy-distributed-analytics-with-irmin-10.md @@ -45,7 +45,7 @@ operations that are available and how to define atomic operations; and

Irmin now exposes Irmin.Type to create new mergeable contents more easily. For instance, the following type defines the property of simple metrics, where name is a human-readable name and gauge is a -metric counting the number of occurences for some kind of event:

+metric counting the number of occurrences for some kind of event:

type metric = {
   name : string;
   gauge: int64;
@@ -232,5 +232,3 @@ operations to read and write atomically. Finally, flexible first-class
 support for immutable trees has also been added.

Send us feedback on the MirageOS mailing-list or on the Irmin issue tracker on GitHub.

- - diff --git a/data/planet/ocamlpro/2022-at-ocamlpro.md b/data/planet/ocamlpro/2022-at-ocamlpro.md index 4c44f200a6..86613ba4e0 100644 --- a/data/planet/ocamlpro/2022-at-ocamlpro.md +++ b/data/planet/ocamlpro/2022-at-ocamlpro.md @@ -22,7 +22,7 @@ source:

Clear skies on OCamlPro's way of life.
- +

For 12 years now, OCamlPro has been empowering a large range of customers, @@ -155,7 +155,7 @@ application (COBOL).

The M language, designed in the 80s to compute the French Income Tax, is still being rewritten in OCaml!
- +

In 2022, our work on MLANG has passed a significant milestone: our work may no @@ -188,7 +188,7 @@ post on the matter.

Cobol is ran in gargantuan infrastructures of many an insurance companies and banks across the globe.
- +

In 2022, we started contributing to the GnuCOBOL @@ -229,7 +229,7 @@ standard. More on this next year, hopefully !

Kind words sent our way by Florian Gilcher (skade), managing director at Ferrous Systems!
- +

OCamlPro's culture is one of human values and appeal for everything scientific.

@@ -257,7 +257,7 @@ contributions and missions, some of which we will share with you right now.

Ecore is the code generator at the heart of the EMF Architecture.
- +

In 2022, we have seized the opportunity to work at the threshold between Java @@ -296,7 +296,7 @@ future iterations of their internal projects.

Ferris the Crab is the mascot of the Rust Language. No wonder why we converged as well!
- +

As we continue scouring the market for more and more Rust projects, and whenever @@ -373,7 +373,7 @@ DNS provider, and strives to offer a user-friendly and easy configuration.

WebAssembly is used to compile many languages to an efficient portable code for web-browsers.
- +

Late 2022 was finally time for us to put into practice the knowledge we have @@ -444,7 +444,7 @@ of Paris-Saclay.

Alt-Ergo proves mathematical formulas corresponding to software program properties.
- +

@@ -469,7 +469,7 @@ full-time R&D engineer.

The dedicated members of the Club!
- +

This is the reason why we would like to thank our partners from the Alt-Ergo @@ -527,7 +527,7 @@ the Formal Methods Lab (LMF) and the ProofinUse consortium members. Stay tuned!<

- +

Dolmen is an OCaml Library developed by @@ -568,7 +568,7 @@ scientists.

opam, the OCaml Package Manager, remains one of OCamlPro's greatest achievements!
- +

2022 has been the theatre of a sustained and continuous effort from the opam @@ -616,7 +616,7 @@ repository, OCaml tooling) and the public's feedback and vision.

Flambda2 is a powerful code optimizer for the OCaml compiler strong of many years of R&D.
- +

OCamlPro is proud to be working on Flambda2, an ambitious OCaml @@ -667,7 +667,7 @@ OCaml distribution!

Camels going to their pluri-annual OUPS Meet-up.
- +

Just under 10 years ago, Fabrice Le Fessant initiated the very first OCaml @@ -709,14 +709,14 @@ Foundation who graciously pays for the pizzas.

Toulouse also has its set of enthousiastic OCaml supporters.
- +

Fortunately for OCaml Users that live in the French South-West, a new Meet-up is now available to them. On the 11th of October 2022, the first OCaml meet-up in Toulouse happened.

-

The first occurence of the OCaml Users in Toulouse Meetup kicked off with Erik +

The first occurrence of the OCaml Users in Toulouse Meetup kicked off with Erik Martin-Dorel (OCaml Software Foundation) presenting Learn-OCaml who was then followed by David Declerck (OCamlPro) presenting his @@ -742,7 +742,7 @@ OCaml.

ICFP 2022 took place in the beautiful town of Ljubjana, Slovenia.
- +

The OCaml Workshop is an international conference that focuses on everything @@ -771,7 +771,7 @@ editions of the conference!

the JFLA'2022 took place in the beautiful Domaine d'Essendiéras in Périgord, France.
- +

Among the many scientific conferences we attend on an annual basis, the @@ -803,4 +803,3 @@ support and collaboration throughout the year,

And to you, dear reader, thank you for tagging along,

Since 2011 with love,

The OCamlPro Team

- diff --git a/data/planet/ocamlpro/better-inlining-progress-report.md b/data/planet/ocamlpro/better-inlining-progress-report.md index 11f0c1a003..29aba1b17f 100644 --- a/data/planet/ocamlpro/better-inlining-progress-report.md +++ b/data/planet/ocamlpro/better-inlining-progress-report.md @@ -74,7 +74,7 @@ and b = (a.v, a.v)

I have a few solutions, but not sure yet which one is best. This probably won't appear in any normal test. This bug manifests through a segmentation fault (cmmgen fails to compile that recursive value reasonably).

Pattern-Matching

-

The new passes assume that every identifier is declared only once in a given module, but this assumption can be broken on some rare pattern matching cases. I will have to dig through matching.ml to add a substitution in these cases. (the only non hand-built occurence that I found is in ocamlnet)

+

The new passes assume that every identifier is declared only once in a given module, but this assumption can be broken on some rare pattern matching cases. I will have to dig through matching.ml to add a substitution in these cases. (the only non hand-built occurrence that I found is in ocamlnet)

Known Mis-compilations

  • since there is no cross-module information at the moment, calls to functions from other modules are always slow. @@ -84,4 +84,3 @@ and b = (a.v, a.v)

What's next ?

I would now like to add back cross-module information, and after a bit of cleanup the first series of patches should be ready to propose upstream.

- diff --git a/data/planet/ocamlpro/flambda2-ep-4-how-to-write-a-purely-functional-compiler.md b/data/planet/ocamlpro/flambda2-ep-4-how-to-write-a-purely-functional-compiler.md new file mode 100644 index 0000000000..97225ad91f --- /dev/null +++ b/data/planet/ocamlpro/flambda2-ep-4-how-to-write-a-purely-functional-compiler.md @@ -0,0 +1,533 @@ +--- +title: 'Flambda2 Ep. 4: How to write a purely functional compiler' +description: Welcome to a new episode of The Flambda2 Snippets! Today, we will cover + key high-level aspects of the algorithm of Flambda2. We will do our best to explain + the fundamental design decisions pertaining to the architecture of the compiler. + We will touch on how we managed to make a purely functional opt... +url: https://ocamlpro.com/blog/2025_02_19_the_flambda2_snippets_4 +date: 2025-02-19T08:24:40-00:00 +preview_image: https://www.ocamlpro.com/blog/assets/img/F2S_picture_son_doong_cave.jpg +authors: +- "\n Pierre Chambart\n " +source: +--- + +

+

+

+

+ + As we dive deeper into the Flambda2 Optimising Compiler, who knows what marvels might await us. Picture: Son Doong Cave (Vietnam). Credit: Collected. + +

+ As we dive deeper into the Flambda2 Optimising Compiler, who knows what marvels might await us. Picture: Son Doong Cave (Vietnam). Credit: Collected. +
+

+
+

+

Welcome to a new episode of The Flambda2 Snippets!

+

Today, we will cover key high-level aspects of the algorithm of Flambda2. We +will do our best to explain the fundamental design +decisions +pertaining to the architecture of the compiler. We will touch on how we managed +to make a purely functional optimising compiler (leveraging +tail-recursion, +backtracking, and non-linear traversal) by covering how the code is traversed, +what actions this design facilitates, and more!

+

All feedback is welcome, thank you for staying tuned and happy reading!

+
+

The F2S blog posts aim at gradually introducing the world to the +inner-workings of a complex piece of software engineering: The Flambda2 Optimising Compiler for OCaml, a technical marvel born from a 10 year-long +effort in Research & Development and Compilation; with many more years of +expertise in all aspects of Computer Science and Formal Methods.

+
+

+

+Expression traversal +

+

Here's a code snippet we would like to be able to optimise and that +demonstrates a set of properties that we want our code optimiser to have.

+
(* original code *)
+let bar x =
+  let d = x + x
+  let y = x, d in
+  y
+
+let foo z =
+  let x, d = bar z in
+  if x = z then x + 1 else d
+
+

We will optimise this code to :

+
let foo z =
+  z + 1
+
+

And we will do that in a single pass that is both efficient and maintainable.

+

Here are the key transformations we would like to apply to this codeblock:

+
    +
  • the first element of the pair returned by the bar function is an alias +to the z argument of foo, thus the if condition in foo +always evaluates to true. +
  • +
  • That means that the d variable is never used, since the else branch in +foo is never executed. +
  • +
+

That being said, to discover the aliased values x and z, we have to +follow the z variable from foo to bar and back again. And to +discover that the let d = x + x is unused in bar we have to know about +the alias and then go back from the d used in foo to the let in +bar. The point is, there is a complex order of dependencies between +these properties that we have to follow in order to learn about the code.

+

Keep in mind that we aim for our compiler to remain reasonably fast. In +order to do that, we conduct all code transformations at the same time as the +analysis. This entails that we cannot just plug a constraint solver inside +of Flambda2 in order to discover these properties.

+

You have to understand that there are two kinds of properties that we want to +track. +One of them, like discovering that the if condition always evaluates +to true, flows in the order of evaluation, i.e: top-down. While the others, +like finding dead code, like let d = x + x, and thus eliminating it, can +only be done in the reverse order of the evaluation, i.e: bottom-up.

+
+

Interesting detail: properties of the first category, sometimes help discover +properties from the second, like in that specific example, but never the +other way round.

+
+

And now, we will explain, how we have designed Flambda2 to be able to operate +within these constraints while transforming the code at the same time.

+
(*
+  CPS-converted version
+  Same code as before in the FL2 IR.
+  All variables with names starting with `k` are continuations.
+*)
+let bar x k_ret =
+  let d = x + x in
+  apply_cont k_ret x d
+
+let foo z k_ret =
+  let_cont k x d =
+    let r = x + 1 in
+    if x = z then
+      apply_cont k_ret r
+    else
+      apply_cont k_ret d
+  in
+  apply bar z k
+
+

If you recall our very first F2S +snippet, we +mentioned one of the fundamental design decisions of Flambda2 which consists +in representing programs using +CPS. One of +the main reasons for that is that inlining becomes very simple.

+

But there's a catch…

+

If you refer back to the original version of the CPS-converted codeblock above, +you will see that if x = z then x + 1 else d is inside the scope of the +the bar function call. It's no longer the case once the function +has been converted to CPS. This shrinking of the scope, is inherent to CPS +representation. In an expression language, value analysis can simply be written +as a recursive function on expressions, propagating properties through an +environment. That is how the simplification pass was written on our previous IR Flambda1. It did +produce some imprecisions here and there, but the trade-off in code simplicity +favoured this route rather than the one we have taken with Flambda2 today.

+

In direct-style language representations, traversals in the order of evaluation +may be roughly emulated by simply traversing the tree recursively. On the other +hand, in CPS-style language representations, this doesn't hold.

+

That's the catch: analysing CPS code entails more complex algorithms.

+

+Overview of the traversal +

+

Reasoning about code requires having a specific kind of data structure.

+

This data structure must behave like a kind of database of properties of +expressions, we naturally attach a name to each expression, and the data +structure itself keeps track of the properties related to them. This data +structure will be named acc in the following code blocks (short for +accumulator).

+

A design decision we made early was that we wanted to traverse the code only +once while doing the maximum amount of simplifications. Of course, there are +exceptions to this rule but that’s a topic for another time.

+

Experience gained from designing Flambda1 guided this decision. In practice, +this overarching traversal manifests itself as two distinct passes: one +downwards and one upwards. The downwards pass performs static analysis and +inlining, while the upwards one handles code reconstruction and dead code +elimination, we call this whole process "Simplify".

+

+Downward traversal +

+

As mentioned in +F2S1, the +FL2 AST is simple and represented with only 6 different cases. You can find it +again below:

+
type expr =
+  | Let_val of { var; prim; body : expr }
+  | Let_cont of { k; param; handler : expr ; body : expr }
+  | Apply_cont of { k; arg }
+  | Apply_val of { f; k_return; arg }
+  | Switch of { arg; cases }
+  | Invalid
+
+

We are going to cover each of these cases separately and explain how each behave +and their role in how they help us reason about the code. Then, once all that is +clear, we will explain how we traverse each constructor. This should help you +understand what information we accumulate during both passes, and what +exactly we can do with them.

+

+Let_val +

+
type expr =
+  | Let_val of
+	{
+	  var : variable ;
+	  prim : named ;
+	  body : expr ;
+	}
+[…]
+
+

Overview and semantics:

+

The Let_val constructor evaluates a named primitive, and binds it to a +variable inside the body and then evaluates that body. A named +primitive is a single atomic operation applied to some variables. Primitives +have no impact on control flow, for instance they cannot raise exceptions.

+

Traversal algorithm:

+

This is the easy case, we just follow the evaluation order above. We analyse +the named primitive, extend the acc data structure with the discovered +properties, and proceed with analysing the body using the new acc.

+

The most important thing about this process on the way down is this specific +extension of the acc data structure. Most other constructors will pipe the +acc smartly all along the computation rather than extending it.

+

Additional details:

+

One interesting thing to note: we can discover properties on the arguments of +the primitive and not only on the bound variable. For example, the primitive +that reads the field of a value allows us to discover that the argument is a +block where that field exists in the current acc.

+

+Let_cont +

+
type expr =
+  | Let_cont of
+	{
+	  body : expr;
+	  k : continuation;
+	  params : variable list;
+	  handler : expr;
+	}
+[…]
+
+

Overview and semantics:

+

The Let_cont constructor evaluates body. body is allowed to refer +to the k continuation, and when encountering an application of k the +control flow will evaluate handler after binding the arguments of the given +application to params.

+

Traversal algorithm:

+

The first thing to note is that there might be several apply_cont to k +inside the body, and since we want to analyse the handler only once, we +cannot just follow the evaluation order naively like with the Let_expr case.

+

Therefore, we first analyse the body, and collect all the data about the +applications of k (see the apply_cont case below).

+

Once we have that, we can analyse and deduce the properties that we can know +about the arguments given to k. We can then bind these properties to the +corresponding parameters and then analyse the handler itself.

+

Quick rundown:

+

Let's consider the following code snippet.

+
let foo_d b k_ret = 
+  let_cont k x =
+    let y = (x <= 1) in
+    apply_cont k_ret y
+  in
+  if b then apply_cont k 0
+  else apply_cont k 1
+
+

When we analyse the let_cont we first analyse the body and see the +conditional on b. We'll see the two apply_conts to k and we'll be able +to deduce that the argument given to k is either 0 or 1. With that +knowledge, we can analyse the handler of k and deduce that y is always +true.

+
    +
  • Side note: +
  • +
+

So far, we've only considered the case where let_conts are not recursive. +We also allow let_cont to be recursive, namely to represent the control-flow +of loops, which means that the handler can contain apply_cont k. Since we +won't be able to see all apply_conts before analysing the handler we will +have to stay conservative by over-approximating the properties we know about +the parameters.

+

+Apply_cont +

+
type expr =
+  | Apply_cont of
+	{
+	  k : continuation;
+	  args : variable list;
+	}
+[…]
+
+

Overview and semantics:

+

As described in Let_cont this only transfers the control to the handler +associated to k using the args to populate the value of the parameters of +k.

+

Traversal algorithm:

+

In this constructor, we extend the acc by associating the current context to +k. This will be retrieved later (see Let_cont case) to know +which contexts led to this continuation, and thus setup a context for the +handler.

+

Furthermore, Apply_cont has no underlying field of type expr so it is +a leaf of the on-going traversal. Assuming that there was a Let_cont earlier, +the traversal will forward the acc to the last Let_cont encountered and +proceed from there again as explained above.

+

If there is no remaining Let_cont then it means that the analysis of the +function is over and that we've traversed all the live code.

+

See the Let_cont example.

+

+Apply_val +

+
type expr =
+  | Apply_val of
+	{
+	  f : variable;
+	  args : variable list;
+	  k_return : continuation;
+	}
+[…]
+
+

Overview and semantics:

+

Apply_val is the usual function application. f is interpreted as a +functional value so control-flow jumps to the associated code, binding args +to the function parameters. Since this is CPS, when the function returns, the +control is transfered to k_return, same as for an Apply_cont, its return +value is bound to the parameter of k_return.

+

It closely ressembles something like:

+
let x = f args in
+apply_cont k_return x
+
+

But since we don't allow normal function applications inside of a Let_val, we +have an Apply_val constructor to handle it.

+

Traversal algorithm:

+

The first thing we do is: recover the known properties about f from our acc.

+

Depending on what properties we have discovered so far, we decide whether to +inline f or not: +If we choose not to inline f, we handle this Apply_val as another +Apply_cont to k_return, but if we do decide to inline it, we replace +the current Apply_val with the body of the f function and continue the +traversal from there.

+

The properties that matter for the inlining decision include:

+
    +
  • Do we know the actual function called (as shown above, f is a variable, +and we may or may not know which function it refers to) +
  • +
  • Are there any user annotation, either on the definition of f such as +[@inline], or at the application, with [@inlined] +
  • +
  • The size of f is important too because inlining large functions may be +detrimental +
  • +
  • The value of the args matter because, for instance, when we know nothing +about the arguments, inlining f is less likely to be benefitial +
  • +
  • In some case, this is where we try Speculative Inlining +
  • +
+
+

Some static analysis requires a whole-view of the program, or at least, the +current function.

+

So when the downwards pass has traversed the whole term, we trigger a few +analyses that we could not do on-the-fly like properties that involve +loops. Such properties can't be computed during a single pass, they usually +require a fix-point. Once that is done, we use the result of the downward pass, +we can use that to initialise the upward environment (uenv).

+

+Upward traversal +

+

You will be happy to learn that the upward traversal is much easier to break +down than the downward one! 🎉

+

+Upward environment +

+

Since we have all the data accumulated on our way down at our disposal, we only +have a few more properties to track on our way back up. As said previously, we +gathered the properties inside an accumulator while following the evaluation +order, on our way down. On our way up, we will feed something more akin to an +environment.

+
(* example of a rebuilding step function *)
+val rebuild_let : var -> prim -> args : var list -> body : (term * uenv) -> term * uenv
+
+

This upward environment (uenv) will mainly hold data about:

+
    +
  • free (live) variables, which are variables that are used in the subterms of +the term being traversed; +
  • +
  • relevant information to aid the Speculative Inlining heuristic, which include +the size of the term and the optimization benefits, for instance the number +of operations eliminated during both traversals. +
  • +
+

These properties are inherently structural. Thus, tracking them is easily done +while traversing the tree in the structural order.

+

Furthermore, these are properties of the rebuilt version of the term, not the +original one:

+
    +
  • Since some optimisations can remove variable uses (making such variables +potentially useless), we are required to work with a rebuilt version of that +term; +
  • +
  • Obviously, optimization benefits can only be computed after actually +performing them; +
  • +
+

That is why we could not have tracked them on the way down, thus relegating +them to the way back up. Hence, we have designed the upward pass to follow the +structural order to track that effortlessly.

+

+Dead code elimination +

+

Free variables are useful for dead code elimination.

+

Dead code is code which can be removed from the term without altering its +semantic.

+

There are two kinds of dead code:

+
    +
  • Pure expressions whose result is never used; +
  • +
  • Code sections that are never reached; +
  • +
+

The first one can be detected by looking for variables which are never +mentioned outside of their definition.

+

The second is the same, but relative to continuation names.

+

In order to understand how it is done, let's see how we do it for a simple +let binding, and then we'll see how it is done through continuations with +let_cont.

+
+

Let-bindings: when rebuilding the let, we have the rebuilt body, and the +set of free-variables of the rebuilt body, and if the variable bound by the +let is not part of the free-variables, we delete that let.

+

Rundown:

+
let x = 1 in
+(* Step 2 *)
+let z = 0 in
+(* Step 1 *)
+let y = x + 1 in
+(* Step 0 *)
+42 + z
+
+

The rebuilding order follows the Step annotations of the example from 0 to 2.

+
    +
  • +

    Step 0: the free-variable of the body of the let y is { z }. y is not +present in that set so we don't rebuild the let. Had we rebuilt it, x would +have been part of the free-variables set. So we just keep { z } as the set of +free-variables.

    +
  • +
  • +

    Step 1: We rebuild the let z and remove z from the free-variables set +because it is now bound.

    +
  • +
  • +

    Step 2: And now we continue onto the let x that we also remove.

    +
  • +
+

We can observe that this method can remove all useless lets in a single traversal.

+

Let's see now, how we can extend this method to rebuilding let_conts while +still maintaining this property.

+
+

Let_conts: As for let_cont, we want to be able to remove the unused +parameters of the continuation. We can see that a parameter is unused after +having analysed the continuation handler: when the parameter is absent from the +set of free-variables of the handler.

+

Furthermore, we need to change the apply_cont of the continuation from which +we remove parameters. We need to only pass arguments for live parameters.

+

That entails to go through the body of the continuation after traversing +its handler, because it's inside the body that apply_conts to that +continuation appear (we are going to put aside recursive continuations for the +sake of simplicity).

+

And so, we keep track of which of these continuations' parameters we removed in +order to rebuild the apply_cont.

+

Rundown:

+
(* Step 0 *)
+let_cont k0 z =
+(* Step 1 (k0 handler) *)
+  return 42
+in
+(* Step 2 (k0 body) *)
+let_cont k1 y =
+(* Step 4 (k1 handler) *)
+  let z1 = y + 1 in 
+(* Step 3 (k1 handler) *)
+  apply_cont k0 z1
+in
+(* Step 5 (k1 body) *)
+apply_cont k1 420
+
+

The rebuilding order follows the Step annotations of the example from 0 to 5, +though, we will only mention the relevant steps.

+
    +
  • +

    Step 1: Parameter z of k0 is dead, so we get rid of it.

    +
  • +
  • +

    Step 3: So now, we have to update the apply_cont k0 z1 which in turn becomes +apply_cont k0 (the argument disappears).

    +
  • +
  • +

    Step 4: Since z1 was deleted, its let is then removed, and y becomes +useless and in turn, eliminated.

    +
  • +
  • +

    Step 5: Eventually, we can replace the apply_cont k1 420 with apply_cont k1 +because the y parameter was previously eradicated.

    +
  • +
+

It is this traversal order, which allows to conduct simplications on CPS in one +go and perform dead code elimination on the upwards traversal.

+
+

+Conclusion +

+

In this episode of The Flambda2 Snippets, we have explored how the Flambda2 +Optimising Compiler performs upwards and downwards traversals to analyze and +transform OCaml code efficiently. By structuring our passes in this way, we +ensure that static analysis and optimizations are performed in a single +traversal while maintaining precision and efficiency.

+

The downward traversal enables us to propagate information about variables, +functions, and continuations, allowing for effective inlining and +simplification. Meanwhile, the upward traversal facilitates optimizations such +as dead code elimination by identifying and removing unnecessary expressions in +a structured and efficient manner.

+

Through these mechanisms, Flambda2 is able to navigate the complexities +introduced by CPS conversion while still achieving significant performance +gains. Understanding these traversal strategies is key to grasping the power +behind Flambda2’s approach to optimization and why it stands as a robust +solution for compiling OCaml code.

+

Thank you all for reading! We hope these articles keep the community eager to +dive even deeper with us into OCaml compilation. Until next time, mind the +stalactites! +⛏️🔦

+ diff --git a/data/planet/ocamlpro/opam-220-release.md b/data/planet/ocamlpro/opam-220-release.md index ddc9bc45d1..5704862082 100644 --- a/data/planet/ocamlpro/opam-220-release.md +++ b/data/planet/ocamlpro/opam-220-release.md @@ -46,7 +46,7 @@ support! A big thank you is due to Andreas Hauptmann (WODI and OCaml for Windows projects were for many years the principal downstream way to obtain OCaml on Windows, Jun Furuse (@camlspotter) whose -initial experimentation with OPAM from Cygwin +initial experimentation with OPAM from Cygwin formed the basis of opam-repository-mingw, and, most recently, Jonah Beckford (@jonahbeckford) whose DkML distribution kept - and keeps - a full diff --git a/data/planet/robur.coop/dnsvizor---run-your-own-dhcp-and-dns-mirageos-unikernel---gets-some-testing.md b/data/planet/robur.coop/dnsvizor---run-your-own-dhcp-and-dns-mirageos-unikernel---gets-some-testing.md new file mode 100644 index 0000000000..8ace3a141a --- /dev/null +++ b/data/planet/robur.coop/dnsvizor---run-your-own-dhcp-and-dns-mirageos-unikernel---gets-some-testing.md @@ -0,0 +1,14 @@ +--- +title: DNSvizor - run your own DHCP and DNS MirageOS unikernel - gets some testing +description: +url: https://blog.robur.coop/articles/dnsvizor02.html +date: 2025-04-10T00:00:00-00:00 +preview_image: +authors: +- Robur Cooperative +source: +--- + + + The NGI-funded DNSvizor provides core network services on your network; DNS resolution and DHCP. + diff --git a/data/planet/robur.coop/git-carton-and-emails.md b/data/planet/robur.coop/git-carton-and-emails.md new file mode 100644 index 0000000000..a4f49827da --- /dev/null +++ b/data/planet/robur.coop/git-carton-and-emails.md @@ -0,0 +1,12 @@ +--- +title: Git, Carton and emails +description: +url: https://blog.robur.coop/articles/2025-01-07-carton-and-cachet.html +date: 2025-01-07T00:00:00-00:00 +preview_image: +authors: +- Robur Cooperative +source: +--- + +A way to store and archive your emails diff --git a/data/planet/robur.coop/pushing-the-opam-repository-into-a-sustainable-repository.md b/data/planet/robur.coop/pushing-the-opam-repository-into-a-sustainable-repository.md new file mode 100644 index 0000000000..2a15bb1610 --- /dev/null +++ b/data/planet/robur.coop/pushing-the-opam-repository-into-a-sustainable-repository.md @@ -0,0 +1,14 @@ +--- +title: Pushing the opam-repository into a sustainable repository +description: +url: https://blog.robur.coop/articles/2025-03-26-opam-repository-archive.html +date: 2025-03-26T00:00:00-00:00 +preview_image: +authors: +- Robur Cooperative +source: +--- + + + The main opam-repository was only ever growing by collecting all releases of all packages. We worked hard on reducing the load for all clients by archiving packages. + diff --git a/data/planet/robur.coop/spf-dkim-dmarc-and-arc.md b/data/planet/robur.coop/spf-dkim-dmarc-and-arc.md new file mode 100644 index 0000000000..b3d895ec13 --- /dev/null +++ b/data/planet/robur.coop/spf-dkim-dmarc-and-arc.md @@ -0,0 +1,12 @@ +--- +title: SPF, DKIM, DMARC and ARC +description: +url: https://blog.robur.coop/articles/2025-04-23-email-verification.html +date: 2025-04-23T00:00:00-00:00 +preview_image: +authors: +- Robur Cooperative +source: +--- + +how emails are verified? diff --git a/data/planet/robur.coop/tcp-miou-and-unikernels.md b/data/planet/robur.coop/tcp-miou-and-unikernels.md new file mode 100644 index 0000000000..a3f771a98d --- /dev/null +++ b/data/planet/robur.coop/tcp-miou-and-unikernels.md @@ -0,0 +1,12 @@ +--- +title: "\u03BCTCP, Miou and unikernels" +description: +url: https://blog.robur.coop/articles/utcp_and_effects.html +date: 2025-03-24T00:00:00-00:00 +preview_image: +authors: +- Robur Cooperative +source: +--- + +My experiment about the TCP/IP stack, effects and unikernels diff --git a/data/planet/robur.coop/whats-new-with-mollymawk.md b/data/planet/robur.coop/whats-new-with-mollymawk.md new file mode 100644 index 0000000000..02d1d27199 --- /dev/null +++ b/data/planet/robur.coop/whats-new-with-mollymawk.md @@ -0,0 +1,14 @@ +--- +title: What's new with Mollymawk? +description: +url: https://blog.robur.coop/articles/mollymawk-first-milestone.html +date: 2025-04-07T00:00:00-00:00 +preview_image: +authors: +- Robur Cooperative +source: +--- + + + In this article we explore the journey Mollymawk has been on, inlcuding getting an (NGI0 core) NLnet grant, updates and more. + diff --git a/data/planet/sfletcher/conversion-operations-of-the-lambda-calculus-.md b/data/planet/sfletcher/conversion-operations-of-the-lambda-calculus-.md index cc078fa42b..f27e769123 100644 --- a/data/planet/sfletcher/conversion-operations-of-the-lambda-calculus-.md +++ b/data/planet/sfletcher/conversion-operations-of-the-lambda-calculus-.md @@ -13,8 +13,8 @@ source: - - + + Conversion @@ -40,9 +40,9 @@ source: \end{eqnarray} \] The $\textbf{semantics}$ of the the $\lambda$-calculus is defined - by three $\textit{conversion rules}$. To understand them + by three $\textit{conversion rules}$. To understand them requires the terminology of $\textit{free}$ and - $\textit{bound}$ variables. An occurence of a variable in a + $\textit{bound}$ variables. An occurrence of a variable in a $\lambda$-expression is bound if there is an enclosing abstraction that binds it, and is free otherwise. For example, in $\lambda x.+\; ((\lambda y. +\;y\; z)\;7)\;x$, $x$ and $y$ appear bound whereas $z$ @@ -56,10 +56,10 @@ source: denotes the application of a particular $\lambda$-abstraction to the argument $4$. The result of applying a $\lambda$-abstraction to an argument is an instance of the body of the - $\lambda$-abstraction in which (free) occurences of the formal + $\lambda$-abstraction in which (free) occurrences of the formal parameter in the body are replaced with (copies of) the argument. Thus, $\left(\lambda x.+\;x\;1\right)\; 4 \rightarrow - +\;4\;1 \rightarrow 5$. In the event there are no occurences of + +\;4\;1 \rightarrow 5$. In the event there are no occurrences of the formal parameter in the abstraction body, the argument is discarded unused so, $(\lambda x.\;3)\;4 \rightarrow 3$. Care is needed when formal parameter names are not unique. For example, @@ -86,10 +86,10 @@ source:
       auto add = [](int x) { return [=](int y) { return x + y; }; };
       auto sub = [](int x) { return [=](int y) { return x - y; }; };
-      [=](int x) { 
+      [=](int x) {
         return [=](int x) {
-          return add (sub (x) (1)); 
-          } (x) (3); 
+          return add (sub (x) (1));
+          } (x) (3);
       } (9) ; //is the value '11'
       
@@ -103,7 +103,7 @@ source: way to look at $\beta$ conversion is that it is saying something about $\lambda$-expressions that look different but mean the same thing. - +

$\alpha$-conversion

@@ -124,7 +124,7 @@ source: does not occur free in $f$, then $\lambda x.f\;x \underset{\eta}{\leftrightarrow} f$. For example, in OCaml if we define f by - let f x = x + 1 then clearly + let f x = x + 1 then clearly fun x -> f x produces the same results for all values x in the domain of f.

@@ -153,7 +153,6 @@ source:

References:
[1] The Implementation of Functional Programming Languages by Simon L. Peyton Jones. 1987.

- + - diff --git a/data/planet/sfletcher/nesting-quoted-strings-in-ocaml.md b/data/planet/sfletcher/nesting-quoted-strings-in-ocaml.md index 539a617433..ca1e618953 100644 --- a/data/planet/sfletcher/nesting-quoted-strings-in-ocaml.md +++ b/data/planet/sfletcher/nesting-quoted-strings-in-ocaml.md @@ -13,12 +13,12 @@ source: - + Quoting

-According to the lexical conventions of OCaml, characters different from \ and " can be enclosed in single quotes and appear in strings. The special characters \ and " are represented in these contexts by their escape sequences. The +According to the lexical conventions of OCaml, characters different from \ and " can be enclosed in single quotes and appear in strings. The special characters \ and " are represented in these contexts by their escape sequences. The escape sequence \\ denotes the character \ and \" denotes the character ".

Here we print the string "Hello world!". The quotes delimit the string and are not themselves part of the string. @@ -33,14 +33,14 @@ To capture the quotes we need to write them into the string by their escape sequ

What now if we wish to quote a string within a string? -

utop[3]> Caml.Printf.printf 
+

utop[3]> Caml.Printf.printf
 "\"A quoted string with \\\"a nested quoted string\\\"\"";;
 "A quoted string with \"a nested quoted
 string\""- : unit = ()
 

We see that in rendering the above string, printf has rendered the escape sequence \" as " and \\\" as \" as required. The pattern continues if we now wish to quote a string within a quoted string within a quoted string. -

utop[4]> Caml.Printf.printf 
+

utop[4]> Caml.Printf.printf
 "\"A quoted string with \\\"a nested \\\\\\\"nested\\\\\\\"
 quoted string\\\"\"";;
 "A quoted string with \"a nested \\\"nested\\\"
@@ -49,24 +49,23 @@ quoted string\""- : unit = ()
 
 

As you can see, things get crazy pretty quickly and you can easily drive yourself mad working out the correct escape sequences to get the desired nesting!

-

Here's a hack : If the string has k levels of quoting, then count how many occurences of \s precede the " at that level. Let that number be n say. To get the next level of quoting you need to concatenate a sequence of n + 1 \s to them to get a total of 2n + 1 \s. To illustrate, look again at the last example: -

utop[4]> Caml.Printf.printf 
+

Here's a hack : If the string has k levels of quoting, then count how many occurrences of \s precede the " at that level. Let that number be n say. To get the next level of quoting you need to concatenate a sequence of n + 1 \s to them to get a total of 2n + 1 \s. To illustrate, look again at the last example: +

utop[4]> Caml.Printf.printf
 "\"A quoted string with \\\"a nested \\\\\\\"nested\\\\\\\"
 quoted string\\\"\"";;
 "A quoted string with \"a nested \\\"nested\\\"
 quoted string\""- : unit = ()
 
That's three level of quoting. At the third level we have the sequence \\\\\\\". That's 7 \s. To quote to the fourth level then we need 8 + 7 = 15 \s: -
utop[5]> Caml.Printf.printf 
+
utop[5]> Caml.Printf.printf
 "\"A quoted string with \\\"a nested \\\\\\\"nested
 \\\\\\\\\\\\\\\"nested\\\\\\\\\\\\\\\" \\\\\\\" quoted string\\\"\"";;
 "A quoted string with \"a nested \\\"nested
 \\\\\\\"nested\\\\\\\" \\\" quoted string\""- : unit = ()
 
- +

In general, the number of \s required for n levels of quoting is 2n - 1 (that is, an exponential function). The solution follows from the recurrence relation Q0 = 0 and Qn = 2Qn - 1 + 1 which in fact establishes a connection to the "Towers of Hanoi" problem.


- diff --git a/data/planet/sfletcher/preprocessor-extensions-for-code-generation.md b/data/planet/sfletcher/preprocessor-extensions-for-code-generation.md index 7f8c7198ca..8a0a6203a5 100644 --- a/data/planet/sfletcher/preprocessor-extensions-for-code-generation.md +++ b/data/planet/sfletcher/preprocessor-extensions-for-code-generation.md @@ -13,7 +13,7 @@ source: - + PPX @@ -26,8 +26,8 @@ source:

The problem treated here is one posed in Whitequark's blog : "Implement a syntax extension that would accept type declarations of - the form - type t = A [@id 1] | B of int [@id 4] [@@id_of] + the form + type t = A [@id 1] | B of int [@id 4] [@@id_of] to generate a function mapping a value of type t to its integer representation."

@@ -39,7 +39,7 @@ source: items. Type declarations are structure items as are let-bindings to functions.

-

In this program, analysis of an inductive type declaration t +

In this program, analysis of an inductive type declaration t may result in the production of a new structure item, the AST of an of_id function to be appended to the structure containing t.

@@ -96,7 +96,7 @@ source: type_declaration = type_declaration_mapper; constructor_declaration = constructor_declaration_mapper }
- +

Implementing the mappings

To warm up, lets start with the easy mappers.

The role of type_declaration_mapper is a function @@ -130,7 +130,7 @@ source: {(default_mapper.constructor_declaration mapper decl) with pcd_attributes=attrs}

Now to the raison d'etre of the - ppx, structure_mapper. + ppx, structure_mapper.

First, a utility function that computes from a constructor_declaration with an @id @@ -164,7 +164,7 @@ source: (*Many "@id"s*) | (_ :: _) -> raise (Location.Error (Location.error ~loc - "[@id] : Multiple occurences"))

+ "[@id] : Multiple occurrences"))

One more utility function is required.

eval_structure_item item acc computes structure items to push on the front of acc. If item @@ -194,7 +194,7 @@ source: (*No [@@id_of]*) | [] -> default_mapper.structure_item mapper item :: acc - (*At least one [@@id_of] (treat multiple occurences as if + (*At least one [@@id_of] (treat multiple occurrences as if one)*) | _ -> (*Cases of an [id_of] function for [t], one for each @@ -219,7 +219,7 @@ source: (*Case this structure item is something other than a single type declaration*) | _ -> default_mapper.structure_item mapper item :: acc

- +

Finally we can write structure_mapper itself as a simple fold over a structure.

let structure_mapper
@@ -233,7 +233,7 @@ source:
   

ocamlc -o ppx_id_of.exe  -I +compiler-libs ocamlcommon.cma ppx_id_of.ml
When built, it can be tested with a command like ocamlc -dsource -ppx ppx_id_of.exe test.ml. - +

For example, when invoked on the following program,

type t =
@@ -278,7 +278,7 @@ source:
                           let id_of = function | U  -> 0  end
       end
   end
- +

References:
@@ -288,6 +288,3 @@ source:

- - - diff --git a/data/planet/signalsandthreads/finding-signal-in-the-noise-with-in-young-cho.md b/data/planet/signalsandthreads/finding-signal-in-the-noise-with-in-young-cho.md new file mode 100644 index 0000000000..ac1916ae18 --- /dev/null +++ b/data/planet/signalsandthreads/finding-signal-in-the-noise-with-in-young-cho.md @@ -0,0 +1,13 @@ +--- +title: Finding Signal in the Noise with In Young Cho +description: +url: https://signals-threads.simplecast.com/episodes/finding-signal-in-the-noise-with-in-young-cho-qBmfD9v_ +date: 2025-03-12T14:41:48-00:00 +preview_image: +authors: +- Signals and Threads +source: +--- + +

In Young Cho thought she was going to be a doctor but fell into a trading internship at Jane Street. Now she helps lead the research group’s efforts in machine learning. In this episode, In Young and Ron touch on the porous boundaries between trading, research, and software engineering, which require different sensibilities but are often blended in a single person. They discuss the tension between flexible research tools and robust production systems; the challenges of ML in a low-data, high-noise environment subject to frequent regime changes; and the shift from simple linear models to deep neural networks.

You can find the transcript for this episode on our website.

+ diff --git a/data/planet/tarides/-fosdem-2025-report-from-the-friendly-functional-languages-bof-room.md b/data/planet/tarides/-fosdem-2025-report-from-the-friendly-functional-languages-bof-room.md new file mode 100644 index 0000000000..b13ec5473b --- /dev/null +++ b/data/planet/tarides/-fosdem-2025-report-from-the-friendly-functional-languages-bof-room.md @@ -0,0 +1,34 @@ +--- +title: ' FOSDEM 2025: Report from the Friendly Functional Languages BOF Room' +description: Several of my colleagues and I went to FOSDEM 2025 and met many functional + programming enthusiasts, sparking great conversations for next year's FOSDEM. +url: https://tarides.com/blog/2025-03-28-fosdem-2025-report-from-the-friendly-functional-languages-bof-room +date: 2025-03-28T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/Brussels-fosdem-1360w.webp +authors: +- Tarides +source: +--- + +

On Thursday, January 30, 2025, I spontaneously decided to join three of my colleagues, Jules Aguillon, Xavier Van de Woestyne, and Paul-Elliot Angles d'Auriac, in attending FOSDEM 2025.

+

When I realised that FOSDEM was still taking proposals for Birds-of-a-Feather (BOF) sessions, I submitted a proposal to organise a Functional Languages BOF session around the idea of gathering the Functional Programming community to showcase projects and elegant solutions to real world programming problems.

+

I was surprised and happy when the proposal was accepted by the FOSDEM organisers late Saturday night, during the conference, leaving just enough time to prepare and call in the Functional Programming community at FOSDEM for our Sunday afternoon session. Thankfully, FOSDEM runs a Matrix chat server for the conference, so it was simple to announce this last-minute addition to the conference schedule.

+

Arriving at the Friendly Functional Languages BOF Room

+

On Sunday afternoon, almost 50 functional programming enthusiasts filled room H.3242 for our "Friendly Functional Languages Show and Tell" session. The turnout exceeded our expectations by far and represented a diverse cross-section of the functional programming community. We had developers from various language communities including OCaml, Gleam, Elm, Elixir, Haskell, and several others.

+

Show and Tell

+

The format was intentionally casual – a space for practitioners to share real-world code they're proud of and discuss practical applications of functional programming principles.

+

During these open sessions, participants presented programming techniques, API choices, interaction with an IDE, concepts inherent to programming and, of course, their projects! We saw parser combinators (live-coded in Haskell), the use of a monad to implement ‘undo’ functionality over composable operations (which Paul-Elliot presented in the context of his personal OCaml project Slipshow), compile-time SQL query generation in Gleam, effect abstraction in Haskell, and a turn-based videogame with a frontend built on Elm. It was clear that people are active and that they have a lot to say in 5 minutes!

+

I found it very interesting to see people demonstrate how functional programming can elegantly solve complex problems.

+

Looking Forward: Organising an FP Dev Room 2026

+

Perhaps the most exciting outcome of our BOF session was the discussion we initiated towards the end of the session about establishing a Functional Programming dev room at FOSDEM 2026. Since only the most mainstream programming languages have a realistic chance at having their application for a dev room at FOSDEM accepted, many attendees expressed interest in creating a space for FP languages next year, and several volunteered to help organise it.

+

We did a quick brainstorming session on what kinds of sessions an FP dev room at FOSDEM should host in order to achieve more visibility of functional programming in the Open Source scene. A major theme that emerged is that we need to show what can be and is being built with these languages in production environments. For example, OCaml is used by Ahrefs to build their leading SEO platform and by Jane Street to power their trading operations, which handled $17 trillion worth of securities trades in 2020 using a codebase of 65 million lines of OCaml. Erlang is another example, as it is used to power WhatsApp, supporting billions of active users.

+

Engaging the Open Source Community

+

As a Developer Advocate for OCaml at Tarides, I was happy to connect with developers and organisations within the Open Source software ecosystem. Several developers curious about OCaml volunteered to participate in recorded user testing sessions for the OCaml tooling we're developing at Tarides.

+

These kinds of direct interactions are invaluable for understanding how developers approach OCaml, what challenges they face, and what opportunities exist to make the language more accessible and powerful. People's willingness to contribute time to help improve the ecosystem speaks volumes about the collaborative spirit of the open-source community.

+

Final Thoughts

+

Organising a BOF session at FOSDEM was a somewhat spontaneous decision, but it proved to be an excellent opportunity to bring together functional programming enthusiasts in an informal setting.

+

I'm looking forward to seeing how the seeds planted during this session grow into a more established functional programming presence at FOSDEM 2026. If you're interested in joining the organising team for next year's prospective FP dev room at FOSDEM, feel free to reach out to sabine@tarides.com.

+

Thank you to everyone who attended and made the session such a success!

+

Connect with Tarides online on Bluesky, Mastodon, Threads, and LinkedIn or sign up for our mailing list to stay updated on our latest projects.

+

Sabine Schmaltz is a Developer Advocate at Tarides, focusing on OCaml community engagement and developer experience.

+ diff --git a/data/planet/tarides/expanding-dune-package-management-to-the-rest-of-the-ecosystem.md b/data/planet/tarides/expanding-dune-package-management-to-the-rest-of-the-ecosystem.md new file mode 100644 index 0000000000..95c1629ffd --- /dev/null +++ b/data/planet/tarides/expanding-dune-package-management-to-the-rest-of-the-ecosystem.md @@ -0,0 +1,71 @@ +--- +title: Expanding Dune Package Management to the Rest of the Ecosystem +description: Explanation of our learnings from attempting to build all Dune packages + in opam-repository using Dune package management. +url: https://tarides.com/blog/2025-04-11-expanding-dune-package-management-to-the-rest-of-the-ecosystem +date: 2025-04-11T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/dunepkgmain-1360w.webp +authors: +- Tarides +source: +--- + +

Since we published The Dune Developer Preview a lot of things have improved on the package management front. While the developer preview has demonstrated how Dune can manage dependencies in a unified workflow, we have been working on making it practical for more projects to adopt Dune to handle their package dependencies. Our goal is to slowly move from a developer preview to a mature feature that the general public can use and rely on.

+

What do we mean by maturation? The goal is fuzzy (as with every software, it is never 'done'), but we want to get Dune package management into a shape where we can consistently recommend that people use it for their projects.  They should be confident that their workflows will continue to work while unlocking the new features that Dune package management brings.

+

The core points of this are:

+
    +
  • The OCaml Platform Tools should work at least as well with Dune package management as they work with opam. With the new features in Dune, this interoperability should work even better as users do not have to share dependencies with the project in the local switch since tools can be installed automatically, possibly even from precompiled binaries. Do you want MDX? Declare a dependency, and voila, you have MDX.
  • +
  • Most projects can start using Dune with little to no adjustments. The majority will work out of the box, and the most frequent fix required is to correct the list of project dependencies. No substantial code changes are necessary, and all projects should continue to be compatible with both opam and dune; there is no lock-in to one tool or the other.
  • +
+

Our goal is to successfully build as many projects as possible using Dune's package management feature. But to evaluate what we have left to do, we need to know where we stand now. This blog post will give you an overview of the project's scope and biggest challenges. 

+

Building "All" Packages

+

What if we want to try to build all the existing OCaml packages? Opam-repository to the rescue! While it might not include proprietary code bases, there are still a significant number of projects we can try to build with it. Fortunately, there has already been prior work done on this subject. Opam-health-check is an existing tool mostly written by Kate that can determine whether packages can be installed on different historical, current, and future OCaml versions. It continuously monitors the state of the opam ecosystem, which inspired its name.

+

Tarides is running and maintaining multiple opam-health-check instances for the community. The most well-known is check.ci.ocaml.org which regularly builds thousands of opam packages on Linux, freebsd.check.ci.dev which does the same thing but on FreeBSD, and windows.check.ci.dev which as the name implies builds packages on Windows to help us with the effort to deliver a better OCaml experience on Windows.

+

We were wondering whether we could use the tool when building with Dune instead of opam. Fortunately, the software is free, so we could extend the functionality to build Dune projects instead of installing opam packages. This gave rise to the next instance of opam-health-check, dune.check.ci.dev which, instead of using opam, builds them using Dune package management.

+

Which Packages are we Building, Actually?

+

Wer misst, misst Mist. – German proverb

+

Opam takes its installation instructions from the opam metadata files that are collected in opam repositories like opam-repository. This is how the regular opam health check works, it selects (nearly all) packages, and attempts to build them.

+

However, only projects that already use Dune to build can use package management. This happens because, when building a project, you need to know which dependencies to build, where these dependencies get built and installed, and which paths to pass to the compiler so it can find the modules that the dependencies install. Unlike in opam, the packages don't get installed into a location containing all installed libraries (a switch), but into separate directories that will be composed together when building.

+

That means we need to be a bit more selective about which packages we are going to pick for testing. Picking projects that don't use Dune will fail in 100% of the cases and will not let us draw useful conclusions besides telling us that you need Dune projects to use Dune package management, which we already know. 

+

So, when determining which packages we want to include as our candidates, we need to filter the list of packages to ones that use Dune. The opam-health-check tool expects to call a shell command to generate the list. However, the process of determining which packages count as 'are using Dune' is more complicated, since the best way to determine that would be to detect whether dune build is used in a package and whether the package depends on the dune package.

+

It's a bit fuzzy, but we decided to only include packages that depend on the 'dune' package. This leaves us with a few false positives (e.g. packages that don't support the most recent versions of Dune) and also some false negatives (packages that accidentally capture a 'dune' dependency through their own dependencies), so this will probably need a bit of revision in the future, but for now, it should be good enough.

+

What About the Rest?

+

There are a significant number of projects using Dune and this is far from all of them. While we can't build them directly because every build system works differently, all opam packages can be used as dependencies and should just work.

+

How do we know this? We run different kinds of tests before using an internal tool that is quite similar but less sophisticated than opam-health-check. In a previous run on OCaml 4.14, we tested using an opam package as a dependency, attempting to build a project, and then checking the results. For that test, we selected 2505 opam packages (since they were compatible with 4.14, opam install could find a solution) and ran it over a few days. Ultimately, we only had 36 failures; thus, our success rate was a whopping 98%! This means that users can safely start using Dune for package management in their projects as the overwhelming majority of dependencies are compatible.

+

What is Building a Package, Really?

+

The biggest challenge is that much of the package metadata in the source archives is incorrect. As a result, dune pkg lock almost certainly picks invalid versions of dependencies. Why is that?

+

Dependencies Galore

+

Opam installs packages by inspecting the files in its own metadata repository, opam-repository. This repository is created by authors submitting their packages on release, and from there on, it is maintained by the opam-repository maintainers. They will make sure to add dependencies that have been accidentally left out or adjust when new, incompatible versions of dependencies get published. Older package definitions will be updated to include upper version constraints.

+

However, if we check out a repository via git or download the source archive and try to build it with Dune, we don't have all these updates. Without them, many packages will fail to build (be it with opam or Dune).

+

These issues can often be fixed very easily by the author of the package, and having Dune fail to build packages due to invalid dependencies is very disappointing. If the dependencies were to be fixed, the project would either work just fine with Dune package management (success, hooray!) or at least fail with a more interesting error. Marking it as a dependency failure does us a disservice by hiding potential errors.

+

Our hack to test for Dune package management compatibility rather than accurate dependency declarations was to replace the dependencies from the source archive with information from opam-repository. This was a two-step process:

+
    +
  1. Overwriting the opam files with the opam files from opam-repository.
  2. +
  3. Removing the dependency information from dune-project because Dune prioritises the information in this file by default.
  4. +
+

Step two had an additional challenge as the dune-project file is in S-expression syntax, but the usual helpful processing tools like jq do not support S-expressions. So, we used Jane Street's sexp tool to do the processing, along with a generous helping of common Unix shell tools.

+

This is not to say that users should be migrating their dependency specifications out of dune-project (they shouldn't), but for our automated processing it was easier to take the updated opam files and use them as-is, instead of migrating them back into the dune-project syntax.

+

What is a Package, Actually?

+

When opam builds a package that uses Dune, it usually calls dune build -p <package-name>, which makes Dune ignore everything in the source repository that is not attached to the package name. However, it doesn't work for the health check, as you want all projects in the source archive to be built, not just the current one that is to be tested. But you also don't want to build every package from the source archive, as that might introduce additional dependencies and unrelated failures. Likewise, you don't want to build code that is not part of any package (e.g. examples, benchmark, utilities).

+

In the end, we solve it by determining the internal dependencies of the project to be built and then collecting these dependencies. We start the build by calling dune build --only-packages <packages-discovered> to restrict the build to only these packages.

+

Ok, Ok, but Show Me the Results!

+

Output of a run of opam-health-check building Dune packages, ordered by amount of reverse dependencies

+

The output of these runs is published on dune.check.ci.dev, where we build the candidate packages on Linux amd64 using the Dune developer preview binaries. We chose this platform because it will give us the biggest set of candidates since most packages are developed on systems similar to it. On the website, you can see all the packages we selected and the result of the build. At the time of writing we have selected 2243 packages to build and 1866 have completed the build successfully, which means that, at the time of writing, we have an 83% success rate in building projects directly! For the remaining 377 packages, the failures can be seen when clicking the entries since opam-health-check keeps logs of all the builds. It is our main tool to determine which issues to tackle next. So as we go forward we expect the success rate to rise to match opam as closely as possible!

+

Where Do We Go From Here?

+

Now that we have opam-health-check running and reporting build successes and failures, we can look into the build issues that it has revealed. A lot of them were small stumbling blocks which could have nevertheless been blockers to adoption:

+
    +
  • The potentially simplest issue arose from the Dune not supporting packages distributed in ZIP archives. Due to OCaml's strong origins on Unix, most packages are distributed as compressed tarballs (often gzip or bzip2 compressed). However, especially on Windows, the ZIP format is more popular and is also supported in opam. In #11511, we added Dune support for uncompressing ZIP files. We usually call programs to decompress the data to avoid shipping implementations of compression algorithms. However, to use these programs, they need to be available, and what is available depends on the platform. The simplest command to call is unzip from the Info-ZIP project. Still, on some platforms, the tar command also supports decompressing ZIP files as if they were tarballs, so we're trying to use whatever the user might have available.
  • +
  • When pinning a package, we assume it uses Dune. This works most of the time because a significant number of packages use Dune to build, but if a package does not, we will have to build and install it using the commands that it declares in its opam file. #11513 does just that. It extracts the commands when pinned and uses them when the pinned package needs to be built.
  • +
  • A somewhat obscure semantic of the way dependencies and conflicts are represented in opam files is that packages which are dependencies are implicitly conjunctions (depending on foo, bar means depending on foo AND bar); however, for conflicts, they are implicitly disjunctions (conflicting with foo and bar means to conflict with foo OR bar). This makes a lot of sense intuitively but is easily forgotten. Dune used to accept a conflict only if all packages were conflicting, and this behaviour flew under the radar for a long time because conflicts are rare. Most of the time, the conflict is only a single package, in which case it doesn't make a difference. This was fixed in  #11515, which also simplified the code.
  • +
  • When solving a project's dependencies, the solver has to go through all of them and find a solution that satisfies all constraints, or it will display an error. These constraints are usually declared in your dune-project or .opam files, but when using Dune package management, there is an additional constraint: the solution needs to be buildable with the currently running version of Dune. Unfortunately, in such a case, the solver would crash. In #11554, we solved the issue to some degree: instead of crashing, the solver will display an error message, which will hopefully make it clearer why it can't find a solution.
  • +
  • Opam has a little-known but very useful feature when declaring package dependencies. Instead of depending on a specific version, the user can use the current version of the package as a variable. This allows projects that consist of multiple packages to depend on each other without having to update all dependencies on every release (an example of this is ocaml-zmq, which comes with async and lwt variants which depend on a common core). However, these constraints don't matter much when building the packages, so we always set the version to dev. Unfortunately, this can cause subtle issues where no solution can be found, so in  #11517, the code was changed to attempt to read the version fields to populate the variable with the value the user declared.
  • +
  • At the moment, Dune handles the compiler in a special way. When attempting to build the compiler, instead of building it in the project, it will build it in a separate location in the user's home directory. This is due to the fact that the compiler can't be moved to a different location at the moment (work is underway to improve the situation - that effort is called "relocatable OCaml"). How OCaml 5.3.0 is packaged in opam-repository changed and introduced a new transitive dependency for the compiler. Thus, the code would not be able to properly detect which opam package is the compiler. This was fixed in #11310 by computing the dependency cone of all possible compiler packages that are currently used to detect which package contains the compiler.
  • +
  • Opam has a way to mark a package as 'do not pick this package unless requested explicitly' - avoid-version. This is, for example, used to mark beta versions of packages that can be installed manually but should not be automatically picked. The solver in Dune does not have such a feature, so originally, Dune sorted these packages to the end of the candidate list, but it would not match the semantics of opam. Dune would then interpret them as forbidden dependencies. However, some older packages failed to build without access to these dependencies, so #11494 was implemented where, instead of failing, the solver tries to minimise the number of dependencies picked that have the avoid-version flag.
  • +
  • Findlib, the tool whose package specification format is prevalent in the OCaml ecosystem and is also used by Dune, has a feature where parts of packages are installed in subdirectories. These subdirectories can also be optional when certain package features are enabled or disabled during building. It is a rare feature, but some real-world packages use it. Unfortunately, Dune would always assume that these directories existed if they were declared and try to read their contents. But if the directory does not exist (e.g. the feature is disabled), this would lead to a crash. The fix in #11569 is short and shows that all bugs are shallow if enough eyes inspect the code.
  • +
+

Fixing these issues has gotten us to an (at the time of writing) 83% success rate in building projects according to opam-heath-check. That's a pretty good result and makes us confident that the package management feature is on the right track.

+

The issues above, as well as future issues related to package coverage and their status, are collected in a tracking issue on the Dune bug tracker.

+

How You Can Help

+

If you want to take part in improving our OCaml ecosystem to have a simple, one-stop-shop for building and installing packages check out the nightly developer preview and try it with your projects. The team is looking for feedback on how they can improve Dune package management, so please share your thoughts on Discuss, and report any issues on GitHub!

+

Stay in touch with us on Bluesky, Mastodon, Threads, and LinkedIn. We look forward to hearing from you!

+ diff --git a/data/planet/tarides/feature-parity-series-restoring-the-msvc-port.md b/data/planet/tarides/feature-parity-series-restoring-the-msvc-port.md new file mode 100644 index 0000000000..2c11d4f293 --- /dev/null +++ b/data/planet/tarides/feature-parity-series-restoring-the-msvc-port.md @@ -0,0 +1,46 @@ +--- +title: 'Feature Parity Series: Restoring the MSVC Port' +description: Discover everything that went into bringing MSVC support to OCaml 5 including + C11 atomics, bug reports, winpthreads, and CI updates. +url: https://tarides.com/blog/2025-04-23-feature-parity-series-restoring-the-msvc-port +date: 2025-04-23T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/manycomputers-1360w.webp +authors: +- Tarides +source: +--- + +

After the release of OCaml 5, restoring any features that were left out of the initial release has been a high priority for our teams and collaborators. We call this effort our 'feature parity' project, and compaction is one example of a feature being brought back to OCaml 5 under its banner.

+

In this post, we look at another returning property, MSVC support, and the steps along the path to implementation. If you want to skip straight to the code, check out the #12954 pull request (and the dozen more linked from it!) in the OCaml repo. Let's dive in!

+

MSVC Support for OCaml on Windows

+

First, let's explain what 'MSVC support' means. In general, OCaml supports compilation to Windows through three separate toolchains: Cygwin, mingw-w64, and MSVC. The mingw-w64 toolchain was available for OCaml 5 from the moment the update launched. Cygwin was restored in OCaml 5.1, but MSVC support has lagged behind until now!

+

The delay stemmed from MSVC's initial incompatibility with C11 atomics, which the OCaml 5 runtime requires. David Allsopp had been exploring possible ways to overcome this incompatibility, testing how C++ atomics worked with older compilers. Eventually, however, Microsoft introduced support, albeit experimentally.

+

To restore the port, the team needed to ensure that the C11 atomics support was reliable, port winpthreads onto MSVC, and create a continuous integration (CI) workflow.

+

Since it is Microsoft's own C/C++ compiler, MSVC is popular and well-known to many developers and Windows users. Bringing compatibility with the compiler to OCaml 5 is an important step towards enabling more users to adopt the latest version of OCaml and explore its new features!

+

C11 Atomics and Bug Reports

+

C11 is a version of the C standard. Since the OCaml runtime is written almost entirely in C, the general standard lets us specify which properties of the C compiler can be used to build OCaml. If we didn't rely on a standard, we would have to list supported C compiler versions individually (GCC from one such version, Clang from another such version, etc). Instead, developers know that the OCaml runtime environment supports any C compiler that is C11-compliant.

+

For OCaml 5 and onwards, the C compiler must be C11 compliant and support C11 atomics. All we need to know about atomics for this post is that the C11 atomic spec enables the compiler to help the programmer access data that can be shared between multiple cores. Without it, the developer would need to use other synchronisation mechanisms such as mutexes, that require more code, both to write and to run. So C11 atomics go beyond what most of us associate with atomicity and are key to writing sound and efficient code in a multicore setting.

+

Once the Visual Studio 2022 release introduced experimental support for C11 atomics, it provided a much clearer path for the team to work on restoring MSVC support. This team included David Allsopp, Antonin Décimo, and Samuel Hym from Tarides, but of course, the success of the project relied on the collaboration, input, and reviews of many open-source OCaml community members. With C11 atomics support in Visual Studio 2022 being experimental, the team needed to ensure that all the sequential tests passed and identify places where parallel tests failed due to bugs in MSVC. The team created several bug reports against the MSVC compiler as a result of this project.

+

The bug reports include:

+ +

Thanks to great support from Microsoft, these bugs were resolved, and C11 atomics support was satisfactory to enable MSVC support for multicore OCaml. This was the biggest roadblock to the project's success, and with it cleared, the team turned their attention to new challenges.

+

Winpthreads and MSVC

+

The next hurdle on the road to success was another Windows-specific compatibility issue. OCaml 4.* had limited support for threading in the form of the optional systhread library, but the runtime itself made no use of it. That completely changed with OCaml 5! The abstraction used to enable threading support was Unix's posix threads, known as 'pthreads'. At the time, the runtime was prepared in the hope that a Windows version could be implemented in the future.

+

However, the original multicore PR could use the winpthreads part of the mingw-w64 library to provide a pthread implementation for the Windows MinGW port. The intention then was that it would be a temporary workaround allowing all the existing pthreads code to be reused, partly due to the belief that it would only work for mingw-w64 and not for MSVC.

+

Upon further investigation, David discovered a library demonstrating that winpthreads could be compiled with MSVC without introducing too many dependencies. Samuel and Antonin worked on formalising the process of extracting the winpthreads sources from the mingw-w64 project to use them for the MSVC port. Antonin also contributed directly to the mingw-w64 project to patch its winpthreads component.

+

Thanks to this work, the initially temporary winpthreads workaround has been implemented as a submodule for MSVC. This lets the new MSVC port use pthread.h via the winpthreads submodule (instead of using winpthreads implicitly as provided by the mingw-w64 GCC compiler).

+

The future of pthreads in OCaml is still up for discussion, with one school of thought being that reimplementing OCaml's use of pthreads in a more abstract way would allow its primitives to function without the full weight of the POSIX spec, resulting in better performance. Work has started to remove winpthreads and use modern Windows APIs for the MSVC and MinGW-w64 ports.

+

CI

+

Finally, the team added a continuous integration workflow enabling GitHub Actions for MSVC testing.

+

As most OCaml compiler developers use a different port than MSVC, and since there are many differences between MSVC and the other ports, being able to test MSVC in CI helps the developer be confident that their modifications do not break the code. In particular, part of the CI workflow includes a check to make sure the assembly used in the MSVC port (meaning that it's written in MASM syntax) is kept consistent with the assembly used in the MinGW port (written in GNU Assembler syntax). This check has already allowed OCaml core developers to catch a few PRs that only updated the assembler in GNU syntax, catching a problem early and preventing it from affecting the program.

+

A Note on the Unloadable Runtime

+

Before we leave you, let's briefly review another feature parity project, the return of the unloadable runtime. This project was paired with the return of the MSVC port as two features that were important to the community. The 'unloadable runtime' is a feature that cleans up OCaml resources, including the stack, heap sections, code fragments, buffers, tables, and more, when OCaml is used as a shared library. For example, if a host program uses OCaml as a library, when control returns to the host program, the unloadable runtime ensures proper resource cleanup.

+

The return of this feature was requested by the community, and our team worked hard to make the restoration a reality. The PR associated with this effort is #12964, which you can check out to learn more about the process behind the changes. The PR has been merged and is expected to be released with the 5.4 update.

+

Stay in Touch!

+

Keep an eye out for future updates on restored features on our blog. For a broader overview of the 5.3 update, you can check out our release blog post covering the changes.

+

You can connect with us on Bluesky, Mastodon, Threads, and LinkedIn or sign up for our mailing list to stay updated on our latest projects. We look forward to hearing from you!

+ diff --git a/data/planet/tarides/feature-parity-series-statmemprof-returns.md b/data/planet/tarides/feature-parity-series-statmemprof-returns.md new file mode 100644 index 0000000000..38fc5ba526 --- /dev/null +++ b/data/planet/tarides/feature-parity-series-statmemprof-returns.md @@ -0,0 +1,68 @@ +--- +title: 'Feature Parity Series: Statmemprof Returns!' +description: Statmemprof, a statistical memory profiler for OCaml, is now compatible + with OCaml 5! Discover the technical background to the return of the feature. +url: https://tarides.com/blog/2025-03-06-feature-parity-series-statmemprof-returns +date: 2025-03-06T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/statmemprof-1360w.webp +authors: +- Tarides +source: +--- + +

Welcome to part two of our feature parity series! In it, we present returning features that were originally lost when OCaml gained multicore support. The addition of multiple domains means that the underpinning design decisions behind certain features have had to change significantly, and work is ongoing to adapt them and return them to OCaml 5.

+

One of these features is memory profiling, which, after much theoretical consideration, has been successfully adapted to OCaml 5. Memory profiling is an important tool for developers who want to optimise their programs, and our post today delves into OCaml 5’s statistical memory profiler, statmemprof, and its now multicore-compatible design. Let’s explore the journey to its return!

+

What is a Memory Profiler?

+

Developers use memory profilers to understand how their programs use memory. Whether they think it’s using too much, is behaving suspiciously, or want to survey it for comparison’s sake, attaching a memory profiler lets them see how their program allocates memory and keep track of it when it runs. It sounds straightforward, but this is where the challenges begin!

+

One of the first hurdles to clear is the sheer volume of allocated memory. Many programs, and in fact, many of the programs that are likely to be interesting from a memory perspective, allocate millions of bytes of memory over their run time. Running a memory profiler that monitors them all would significantly slow down the entire system. OCaml used to have a memory profiler that monitored all allocations (see spacetime), but it was removed because it was too resource-expensive.

+

The solution to this first conundrum is to use a statistical memory profiler (the ‘stat’ in Statmemprof). A statistical memory profiler monitors a random sample of memory allocations in the program. This method still allows users to find allocations that stand out. Large allocations of memory tend to be more noteworthy, and consequently, if you have a program that allocates small and large pieces of memory, you want the random sampler to sample the bigger ones more often.

+

Implementing this solution first brought Statmemprof to OCaml 4, but that still left the multicore issue, which, apart from making things generally tricky, required the developers to make some key decisions about how memory profiling should work with multiple domains.

+

How Statmemprof Works With OCaml 5

+

Memory Allocation in OCaml

+

There are a few things one needs to wrap one’s head around to understand how statmemprof does its magic. This includes the way OCaml allocates memory with an inline pointer-bump allocator. If you are already familiar with memory allocation in the minor and major heap, jump ahead to the next section!

+

OCaml needs to be able to allocate millions of objects a second and, therefore, needs very efficient memory allocation. Most programming languages call a function in the language library (such as malloc) that determines which memory to allocate. This process is too slow to work well in OCaml and for many other garbage collected languages such as Haskell, which also use bump-pointer allocators.

+

In OCaml, a large part of the total memory available is reserved in what is known as the minor heap. In the minor heap, an allocation register points to the lowest address of allocated memory or to the boundary between what is allocated and free. Say a new object needs 32 bytes of memory: the system subtracts 32 bytes from where the allocation register is pointing and this space is used for the new object. When the minor heap’s garbage collector (GC) runs, it checks which objects can be deleted and which need to be kept. Surviving objects are promoted to the major heap, and the allocator register moves to the top of the minor heap since it is now empty.

+

The minor heap has a ‘limit’, most commonly set to where the heap’s space ends, that, when reached, triggers a jump into the runtime system. The runtime can then take one of several actions, including garbage collection. This design makes memory allocation in OCaml very fast. Crucially for our topic today, this limit can be used to trigger a number of important events. Signal handling, for example, is achieved by tripping the limit in the minor heap to get into the runtime, which then runs the signal handlers. The runtime decides what actions to take and where to set the limit in the minor heap, allowing it to perform many different behaviours.

+

OCaml can also bypass the minor heap and allocate objects directly in the major heap. This is useful for very large objects, which tend to live longer and survive the minor heap’s GC anyway. That's a topic for another time.

+

With this basic overview of how OCaml allocates memory in our back pocket, let’s look at how statmemprof profiles memory in this system.

+

Statistical Memory Profiling in OCaml

+

The key to how statmemprof profiles memory lies in how the ‘statistical’ aspect is defined. To sample only a subset of memory allocations we need to define a workflow by which we get a random selection of samples. Since it only profiles every n number of allocations the user can leave the profiler running in the background without introducing significant overhead.

+

So how does it work? We need to generate a number for both the minor and major heap to help us select the sample we want to profile. We need the number to be random, meaning that every number has an equal probability of being generated. Statmemprof achieves this through statistical sampling using a so-called Bernoulli trial, meaning that it samples every word of memory allocation with the same probability.

+

Say the event we’re interested in is the allocation of a single word of memory to the minor heap. We have a parameter called ‘lambda’ for any such event, which represents the likelihood that statmemprof will sample that particular event. The random number we get, called a geometric random variable, stands for how many Bernoulli trials for some given lambda (or likelihood). You can also think of it as how long do we wait (how many events happen) before we sample one event.

+

This choice of distributions is driven by the sampling mechanics in each heap. For the minor heap, we need to know "when is the next sample due?" which is naturally modeled by a geometric distribution - it tells us how many trials (allocations) until we hit our first success (sample). For the major heap, since we're dealing with larger blocks of memory, we need to know "how many samples should we take in N words?" This is naturally modeled by a binomial distribution, as it represents the number of successes (samples) in a fixed number of trials (N words). The geometric distribution is also computationally efficient for triggering the GC mechanism at the right time, while the binomial distribution provides a more systematic way to sample larger memory blocks.

+

Now, let's imagine we get a random number, say 137. That number is subtracted from the allocation register in the minor heap, and the limit is set there. When the limit is reached, we go into the runtime, and the action we take is to take a memory profile sample. Statmemprof then generates a new number, and the process repeats. The process is the same for the major heap, but we use a binomial random variable instead of a geometric one.

+

The benefit of statistical memory profiling is that smaller-sized objects in the minor and major heaps are less likely to be sampled since they don’t take up as much space as larger objects. This is good because the larger objects tend to be more interesting from a memory profiling perspective.

+

What Happens When Statmemprof Samples an Object?

+

Statmemprof was designed to be a flexible mechanism that gives the programmer a lot of choice. There is no hardwired action set up for when statmemprof samples an allocation. Instead, there are a number of actions to choose from left open for users to configure. They include determining the size of the object, whether it came from the minor or major heap, and what the program was doing at the time of the object’s allocation.

+

When statmemprof samples an allocation it executes a callback (a construct that essentially works like a function) which is provided with details about the allocation and a backtrace. A backtrace refers to the sequence of functions that called a particular function. Backtraces are used to trace backwards from the function that triggered the allocation to the functions that called it, and so on, until it reaches the entry point of the program. What this means for statmemprof is that the API provides enough details for tools like memtrace to generate visual representations of memory use for the user's programs.

+

There are five different kinds of events that can trigger the callback:

+
    +
  1. alloc_minor: an object is allocated to the minor heap
  2. +
  3. alloc_major: an object is allocated to the major heap
  4. +
  5. promote: an object survives garbage collection and is moved to the major heap
  6. +
  7. dealloc_minor: an object does not survive garbage collection and is freed from the minor heap
  8. +
  9. dealloc_major: an object does not survive garbage collection and is freed from the major heap
  10. +
+

So, the hypothetical lifecycle of an object could be as follows: it gets stored in the minor heap with alloc_minor. The limit is tripped in the minor heap, and the garbage collector runs. The object survives garbage collection and is moved to the major heap with promote. The garbage collector runs in the major heap, and if the object is not needed anymore, it gets freed with dealloc_major. As an object's lifecycle progresses, statmemprof will execute a callback for each event and a complete picture of it can be built up. Statmemprof is designed to be flexible and configurable, and, for example, users can choose to set the profiler to retain callback information or opt to discard it.

+

Memtrace

+

For many users, delving into the code to configure statmemprof would add an undesirable level of complexity to their workflow. The solution is to use tools like Memtrace, a profiling library that uses the statmemprof interface. By building on the statmemprof functionality, these tools enable users to profile memory in the way they want to without having to worry about the specifics of how statmemprof works. Memtrace can accumulate the allocations and callstacks from the program to get a picture of which code locations are responsible for triggering allocations. (Note that, as of writing, the 5.3 compatible version of Memtrace has yet to be released by JaneStreet, but work is underway).

+

Memtrace was created at Jane Street to help them pinpoint memory issues like space leaks. It uses the callback API implemented by statmemprof to record allocation events in the binary format Common Trace Format (CTF). Memtrace also comes with a viewer, a helpful tool that lets developers visualise their programs and see how memory is allocated.

+

Generating a trace is straightforward, and Luke Maurer from Jane Street outlines the process in a great blog post on their website, and, if you want to learn more about the design of Memtrace, check out this excellent guide.

+

This is just one example of how restoring statmemprof support brings powerful options to users of OCaml 5. Its features support the creation and implementation of tools that let users manage and understand how their programs use memory in new and detailed ways.

+

Considerations for Multiple Domains

+

So how do multiple domains affect the design choices for a memory profiler? Let’s take a look at some examples:

+
    +
  • Let’s say you have two domains running at the same time doing different jobs separately, then one domain starts profiling its memory allocations. Should memory allocated by the other domain be sampled? The answer is: No! Behaviour in separate domains should be treated independently of each other.
  • +
  • Say you are in one domain and you start profiling, then, from this domain, you spawn another. Should the allocations in the new domain be profiled? The answer is: Yes! Because the new domain was created to achieve the work of the original domain.
  • +
  • In the multi-domain world, one domain can start a ‘profile’ by calling the start function of statmemprof and sets up all the callbacks and sampling separately from all other domains. In theory, you could apply entirely different profiling tools, like memtrace, in different domains in the same program.
  • +
  • Let’s say you run a program on multiple domains and run a profile on one domain which allocates some objects, samples them, and runs the allocated callbacks. Let’s then suppose that that domain terminates but the profile keeps running (say if another domain is running the same profile) and an allocation callback is promoted in the GC and continues its lifecycle. It is generally the rule that callbacks should be run by the domain that allocated the object, but if that original domain has terminated the callback may be run by a different domain because the object might still be alive on the major heap. When the object is freed and statmemprof would need to run a deallocation callback, it can also run that callback from a different domain if the original domain has been terminated.
  • +
  • Should call-backs keep running after the profiler has called stop? In OCaml 4, after stop was called statmemprof would essentially throw away all of its sampled information. In OCaml 5 the user can determine whether to ask the profiler to stop sampling, where statmemprof stops sampling new allocations but keeps the information, or stop and discard where the profiler discards all the information held for that profile. This wasn’t a relevant feature for OCaml 4 since a terminated domain meant the program had ended and statmemprof could just disregard that information. With OCaml 5, longer running memory profiling is more likely, and we need to be able to distinguish between the two stop calls.
  • +
  • Lastly, a lot of work went into synchronisation and ensuring that no domain was ever waiting for statmemprof before being able to continue its jobs. Statmemprof only uses one lock to enforce synchronisation, which occurs when a domain terminates while statmemprof is still running. Its data is put on the orphans list which is protected by a lock. Any other domain can then adopt this data.
  • +
+

Are you using statmemprof? Please provide feedback and raise any issues in the OCaml repo and on the OCaml Discuss forum.

+

Until Next Time!

+

Curious about how we maintain and restore features to OCaml 5? Read more of our multicore and compiler blog posts, such as compaction, compiler maintenance, and catching data races.

+

Connect with Tarides online on Bluesky, Mastodon, Threads, and LinkedIn or sign up for our mailing list to stay updated on our latest projects.

+

Acknowledgements

+

A huge thank you to Nick Barnes and Tim McGilchrist for their invaluable and extensive input on this post.

+ diff --git a/data/planet/tarides/full-blown-productivity-in-vscode-with-ocaml.md b/data/planet/tarides/full-blown-productivity-in-vscode-with-ocaml.md new file mode 100644 index 0000000000..b2defca85a --- /dev/null +++ b/data/planet/tarides/full-blown-productivity-in-vscode-with-ocaml.md @@ -0,0 +1,92 @@ +--- +title: Full blown productivity in VSCode with OCaml +description: More features for ocaml-lsp that enhance productivity when writing OCaml. +url: https://tarides.com/blog/2025-02-28-full-blown-productivity-in-vscode-with-ocaml +date: 2025-02-28T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/adopt_ocaml-1360w.webp +authors: +- Tarides +source: +--- + +

Happy New Year, OCamlers! 🎉 +As we usher in another year, we have something special to celebrate — a New Year's gift that promises to make your coding experience even better! +We have been working on exciting new features in VSCode designed to boost productivity, streamline workflows, and make your development journey smoother and more enjoyable.

+

For users of Emacs, we have a brand new emacs mode for interacting with the lsp server that will make your coding experience as enjoyable as it should be. Check out the Discuss announcement at Release of ocaml-eglot 1.0.0 and the project repository at ocaml-eglot.

+

Without further ado, let's "unwrap" 🎁 these features for your viewing pleasure.

+

1. Type of Selection

+

This feature enhances code comprehension by allowing you to grow or shrink the selection to view updated types at different levels of granularity. You can adjust the verbosity of the type information to suit your needs, providing either a concise or detailed view. This information can be accessed conveniently through the default hover pop-up or via a dedicated output panel, making it adaptable to your workflow.

+

Command name: Get the Type of the Selection

+
    +
  • Command shortcut: Alt + T
  • +
  • Grow Selection: continously press Alt + T
  • +
  • Shrink Selection: Alt + Shift + T
  • +
  • Add Verbosity: Alt + V
  • +
+

Using Alt+T to get the type of Selection

+

Using a dedicated Output Panel

+

In the settings/preferences of the ocaml platform extension, you can toggle an option to display the results of type selection in a dedicated output panel.

+

Toggling the settings to use a dedicated output panel

+

Type Selection with results displayed in a dedicated output panel

+

2. Search by Type or Polarity

+

Looking for functions or values that match a specific type? +The Search by Type/Polarity feature let's you input a type signature, e.g., int -> string or a polarity -int +string, and then it fetches all matching functions and values across your project.

+

Command name: Search a value by type or polarity

+

Command shortcut: Alt + F

+
    +
  • +

    Search by Type +Searching a value by it's type

    +
  • +
  • +

    Search by Polarity +Searching a value by it's polarity

    +
  • +
+

3. Construct Typed Holes

+

This feature let's you construct possible values for a given typed hole.

+

Command name: List values that can fill the selected typed-hole

+

Command shortcut: Alt + C

+

Construct functionality to list values that can fill the selected typed-hole

+

This feature also comes with a configurable option that allows it to construct values for the next typed hole automatically.

+

Setting to toggle construct to be conducted for the next typed hole automatically

+

Performing construct with chaining turned on

+

4. Jump to a specific Target

+

Traditional navigation, while it works, falls short when it comes to navigation in OCaml. This feature provides a seamless way to jump to specific targets which are closest to your cursor in the source code. For example, a large match construct and you could jump from one case to the next effortlesly.

+

Command name: List possible parent targets for jumping

+

Command shortcut: Alt + J

+

At this point, we support the following targets:

+
    +
  • Modules
  • +
  • Functions
  • +
  • Let statements
  • +
  • Match statements
  • +
  • Match cases (previous and next)
  • +
+

Jumping to a specific target

+

5. Navigate Typed Holes

+

This feature let's you navigate to typed holes.

+

Command name: List typed holes in the file for navigation

+
    +
  • As you move through the list with your arrow keys, the cursor jumps to the typed hole to give you a preview. +When you make a selection, the cursor stays there.
  • +
+

Navigating to different typed holes

+
    +
  • If you toggle the Navigate
  • +
+

Setting to automatically perform construct after jumping to a typed hole

+

Automatically performing construct after navigating to a typed hole

+
    +
  • If you don't feel like jumping to a typed hole yet, just hit Esc and your cursor will portal back to it's original position.
  • +
+

Pressing the Escape key to stop operations and return back to the origin cursor position

+

Hope you are excited to try out these new features. It is our wish that you have a much better and smoother experience while coding OCaml in VsCode.

+

Please feel free to open issues if you discover a problematic behaviour:

+ +

You can connect with Tarides on Bluesky, Mastodon, Threads, and LinkedIn or sign up for our mailing list to stay updated on our latest projects. We look forward to hearing from you!

+ diff --git a/data/planet/tarides/mirageos-on-ocaml-5.md b/data/planet/tarides/mirageos-on-ocaml-5.md new file mode 100644 index 0000000000..9fec9bdd69 --- /dev/null +++ b/data/planet/tarides/mirageos-on-ocaml-5.md @@ -0,0 +1,41 @@ +--- +title: MirageOS on OCaml 5! +description: Discover the ongoing work to make MirageOS compatible with OCaml 5 including + the Solo5, Unikraft, and improved cross-compilation efforts. +url: https://tarides.com/blog/2025-02-06-mirageos-on-ocaml-5 +date: 2025-02-06T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/junction-1360w.webp +authors: +- Tarides +source: +--- + +

OCaml 5 brought significant changes to fundamental parts of the language – notably concurrency using effects and multithreaded parallelism. This has caused some features and tools compatible with OCaml 4.14 to be incompatible with the new update, and several projects at Tarides aim to restore compatibility where that is the case. In today’s post, we will focus on the efforts toward creating a MirageOS port for OCaml 5.

+

The main benefit of making MirageOS compatible with OCaml 5 is to make it possible to explore how to best take advantage of features unique to the latest version of the language. An early proof-of-concept thus experimented with replacing Lwt with the new concurrency library Eio. This is just one example, but it illustrates why bringing OCaml 5 support to MirageOS is a high priority for our team.

+

To port MirageOS to OCaml 5 we have been contributing to the port using Solo5 backends but we are also exploring the possibility to use Unikraft backends. The Solo5 port has been released recently, with the versions 1.x of the ocaml-solo5 package on opam. As a complementary effort, work has also been ongoing to make cross-compilation easier in general. This will benefit not just the MirageOS project but also any cross-compilation projects for OCaml in the future. Let’s dive into the updates!

+

The Solo5 Backend

+

The first goal was to restore support for a backend that was available to OCaml 4.14 MirageOS users: Solo5. Solo5 is popular with developers building MirageOS unikernels, and since it is currently the only fully supported base for building a freestanding Mirage application, getting Solo5 support for OCaml 5 is a big step in the right direction for OCaml users.

+

The PRs that introduce OCaml 5.2.1 support via the Solo5 API is the fruit of the collective effort of many developers, including, in no particular order: Pierre Alain, Fabrice Buoro, Romain Calascibetta, Christiano Haesbert, Samuel Hym, @kit-ty-kate, Hannes Mehnert, and many more helpful eyes.

+

So, what is Solo5? Mirage applications can run in a hypervisor, such as KVM or Xen, without a full OS, and Solo5 provides minimal services (such as telling the time, reading or writing a block on the disk or network, etc.) for running an application there. OCaml-Solo5 adds the extra libraries required to build the OCaml runtime on top of Solo5.

+

What has Changed?

+

As you can imagine, the significant features introduced in OCaml 5 depend on correspondingly large changes to its underlying design. These include assumptions of how the OS works, how the C compiler works, and how the build system is set up. All of these modifications have a direct impact on what OCaml-Solo5 must provide to build the OCaml runtime for MirageOS unikernels.

+

If you prefer to dive right into the code changes, I recommend that you visit the PR directly. Otherwise, let’s take a look at what’s new!

+

Nolibc Extensions +The usage of (OS) threads has changed, as well as how memory is managed (relying in particular on mmap/munmap), some C features such as thread-local storage and C11 atomics are now required. Support for all of these must be added in a freestanding setting such as MirageOS, even if Solo5 remains monocore. Therefore, to make OCaml-Solo5 compatible with the latest release, developers have amended the nolibc library and the way the C compiler is invoked. The modifications come in the form of extensions to nolibc, and most of the nolibc extensions included in the PR are inherited from previous PRs by @kit-ty-kate, Romain Calascibetta, and Pierre Alain, including changes to pthread, mmap and TLS.

+

Build System +To address the build system changes, the PR applies version-specific patches to sources when fetched. This replaces the previous method of modifying the OCaml build system with seds and echos. The reasoning behind this change is twofold: Firstly, all bar one of the patches have been designed to improve how the compiler build system supports cross-compilation, simplifying the maintenance of the OCaml and Solo5 compatibility for MirageOS. Secondly, making the modification system into separate patches with full explanation messages makes reviewing them easier and clarifies to the user which modified build system they rely on. A neat bonus of this restructuring is that the .opt versions of the compiler are now also built, which should result in better performance, particularly when building large unikernels.

+

Toolchain +The update also means that the ocaml-solo5 package now installs a new {aarch64,x86_64}-solo5-ocaml-* toolchain. Creating a toolchain avoids baking the build-time directories containing nolibc and openlibm into the generated OCaml compilers. The package generates two versions of the toolchain: one with built-time directories, that is added to PATH only when the compiler builds, and the other with the final destination directories, installed in the bin directory by opam.

+

Beside adding compatibility with OCaml 5 for Solo5, we are also exploring alternative options. In particular, we are working on adding Unikraft support to test whether it can provide better performance.

+

The Unikraft Backend

+

Unikraft is a Unikernel Development Kit that lets users create custom unikernels with a large support for standard APIs to help port applications. It is an open-source project maintained and supported by over fifty active contributors. The main benefit of adding support for a Unikraft backend to MirageOS is to improve I/O performance in comparison to the Solo5 API.

+

Because of these potential benefits, adding the Unikraft backend is a high priority. Currently, there are several repositories being worked on, the most mature of which is ocaml-unikraft. The project is still in an exploratory phase, and more updates will follow when we have more to share.

+

Making the Build of OCaml Cross Compilers Easier

+

In addition to new backends, part of improving the user experience with OCaml 5 has focused on improving the compiler’s build system, in particular regarding cross compilers, which is helpful for MirageOS users since OCaml-Solo5 is really a cross compiler to the Solo5 target.

+

The first step to streamlining the compiler’s build system involved reducing the number of Makefiles down to one, the root Makefile. By bringing all the build logic into one place and avoiding duplication and stacking dependencies, the compiler’s build system is more consistent and easier to use. The effort is split into many PRs, both big and small, including #11243, #11248, #11268, #11420, #11675.

+

In addition to reducing the number of Makefiles, the build system improvements also involved improving ocamldep. It needed to be able to distinguish between source vs build trees and have support for lex and yacc input files. The effort also included breaking the dynlink library’s dependency on compilerlibs to make the build system simpler and faster (#11996).

+

Continuing on this work, several PRs have brought more fixes and improvements to cross-compilation, with more on the way. Currently, the largest upstreamed PRs are #13281, #13282, #13526, and #13312. If you use the new OCaml 5 capabilities in Mirage with either the Solo5 or Unikraft, you can take advantage of the simplified build systems and cross-compilation.

+

Try it Yourself and Stay in Touch

+

OCaml-Solo5 is released and you can get started simply by building MirageOS in a 5.2.1 switch, with no pinning involved. Samuel wrote a quick guide on how to get started with ocaml-solo5 in a Discuss post, and we recommend you give it a try. For Unikraft, keep an eye out for updates as work continues behind-the-scenes.

+

You can connect with us on Bluesky, X, Mastodon, Threads, and LinkedIn or sign up for our mailing list to stay updated on our latest projects. We look forward to hearing from you!

+ diff --git a/data/planet/tarides/ocaml-53-features-and-fixes.md b/data/planet/tarides/ocaml-53-features-and-fixes.md new file mode 100644 index 0000000000..5ac6a30af5 --- /dev/null +++ b/data/planet/tarides/ocaml-53-features-and-fixes.md @@ -0,0 +1,60 @@ +--- +title: 'OCaml 5.3: Features and Fixes!' +description: OCaml 5.3 is released! This post gives you an overview of returning features, + optimisations, and fixes as well as a taste for what's to come. +url: https://tarides.com/blog/2025-01-09-ocaml-5-3-features-and-fixes +date: 2025-01-09T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/OCaml53-1360w.webp +authors: +- Tarides +source: +--- + +

We have a brand new OCaml release on our hands! 5.3 comes packed with features, fixes, and optimisations, including the return of some ‘familiar faces’. Support for the MSVC port is returning, as is statistical memory profiling now compatible with multicore projects.

+

This post highlights new and restored features, notable changes and user experience improvements, plus some bug fixes. There is no way that I can cover everything in this update, so I recommend that you check out the Changes document on GitHub for the full list of contributions!

+

MSVC

+

The 5.3 release restores support for the MSVC port of OCaml on Windows, marking the last remaining platform from 4.x to regain support in 5.x. This is part of a wider effort to achieve feature parity between OCaml 4.14 and OCaml 5, of which compaction is a previous example, making the transition between versions as smooth as possible. The bulk of the effort is summarised in PRs #12954 and #12909 opened by David Allsopp, Antonin Décimo, and Samuel Hym (review by Miod Vallat and Nicolás Ojeda Bär).

+

Since the OCaml 5 runtime uses C11 atomics, supported platforms need to be compatible with them as well. Visual Studio 2022 introduced experimental support for C11 atomics which made the MSVC port of OCaml 5 possible, but the team needed to test out the feature first. This exploratory effort led to several bug reports addressed by Microsoft, and once these were completed (alongside a lot of other work, including fixing the winpthreads library of the mingw-w64 project to that it builds with MSVC), the MSVC port was ready for public release.

+

As part of the project bringing MSVC back the team explored clang-cl, an alternative command line interface to Clang designed to be compatible with the MSVC compiler cl.exe. This was helpful because clang-cl has a different set of warnings and tips to MSVC, and using it effectively gave them a ‘second opinion’ on their code. The main PR for this side of the project is #13093.

+

Statmemprof

+

OCaml 4.14 had support for statistical memory profiling, a feature of the language that can sample memory allocations allowing tools like Memtrace to help users identify how their programs are using memory. The multicore update introduced significant complexity to the process which made it necessary to drop support for 5.0; but work soon commenced to restore support under our feature parity banner! In 5.3, statmemprof makes its return, now equipped with multicore capabilities.

+

So how does it work? Statmemprof can check the allocation of memory at some given frequency (lambda) per word or unit of data. By sampling a fraction of allocations at random, we are able to monitor programs in a language like OCaml which allocates high rates of memory. It would be far too expensive performance-wise to monitor every allocation.

+

The new design has a lot in common with the OCaml 4 implementation of statmemprof, but with several tricky optimisations and changes to account for the significant complication of multiple domains and threads. Delve into the details in the PRs #12923 and #11911 by Nick Barnes (external reviews by Stephen Dolan, Jacques-Henri Jourdan, and Guillaume Munch-Maccagnoni).

+

Deep Effect Handlers

+

OCaml 5.0 came with experimental support for algebraic effects, which allow users to describe computations and what effects they are expected to create. A handler essentially manages a computation by monitoring its execution and keeping track of resulting effects. This ‘management’ can be done in two ways, deeply or shallowly. A shallow effect handler monitors a computation until it either terminates or generates one effect, only handling that effect. A deep effect handler always manages a computation until it terminates and handles all of the effects performed by it.

+

PR #12309 (Leo White, Tom Kelly, Anil Madhavapeddy, KC Sivaramakrishnan, Xavier Leroy and Florian Angeletti, review by the same, Hugo Heuzard, and Ulysse Gérard) introduces effect syntax for deep effect handlers, rules that define the structure for writing them, compatible with the type checker and with support for pattern matching. This change aims to simplify the code needed to use deep effect handlers, improving user experience. Note that you can still use shallow effect handlers, and there is a good tutorial for using both in the correspondingly updated manual page.

+

Debugging Improvements

+

Another long-term project coming to fruition in this update are the several improvements to debugging on macOS. The platform is popular with a wide variety of OCaml users, including compiler developers, and they need good debugging workflows for their programs.

+

LLDB is the only supported native debugger on macOS, for both the ARM64 and x86_64 architectures. The improvements enable several new features:

+
    +
  • #13163 enable frame pointers on macOS x86_64 (Tim McGilchrist, review by Sébastien Hinderer and Fabrice Buoro): This PR introduces support for a common technique used by profiling tools including Linux perf, eBPF, FreeBSD, and LLDB, called stack-walking. Various performance tools use stack walking to reconstruct call graphs for programs, and frame pointers are what enable them to do so.
  • +
  • #13241, #13261, #13271, add CFI_SIGNAL_FRAME to arm64 and RISC-V runtimes for the purpose of displaying backtraces correctly in GDB (Tim McGilchrist, review by Miod Vallat, Gabriel Scherer and KC Sivaramakrishnan): This change helps sync up the runtime for the arm64 architecture for macOS (and the RISC-V runtime) with the amd64 and s390x runtimes. The two additional PRs add improvements to the first.
  • +
  • #13136 Compatible LLDB and GDB Python extensions (Nick Barnes): This PR replaces some old GDB macros (used to debug OCaml programs) with faster and more capable extensions, and makes those extensions available in LLDB. This is especially useful to macOS users who can’t use GDB.
  • +
+

OS-Based Synchronisation for Stop-the-World Sections

+

PR #12579 (B. Szilvasy, review by Miod Vallat, Nick Barnes, Olivier Nicole, Gabriel Scherer and Damien Doligez) improves user experience by replacing generic busy-wait synchronisation with OS-based synchronisation primitives, namely barriers and futexes. The change has significant performance benefits, especially on Windows machines, where spinning was causing long wait times. You can learn more about it in our blog post on the project.

+

User Experience Improvements

+
    +
  • #12868 Refresh HTML manual/API docs style (Yawar Amin, review by Simon Grondin, Gabriel Scherer, and Florian Angeletti): An update to the OCaml Manual which simplifies the colours, removes the gradients, and fixes the search button. It’s a nice improvement to a part of the OCaml ecosystem that is visible to users of all different backgrounds and contexts.
  • +
  • #13201, #13244 (Sébastien Hinderer, review by Miod Vallat, Gabriel Scherer and Olivier Nicole), and #12904 (Olivier Nicole, suggested by Sébastien Hinderer and David Allsopp, external review by Gabriel Scherer) various improvements to TSan: These three PRs represent the continuous work being put in to bring improvements to TheadSanitizer or TSan. They include speedups and the ability for users to choose which PRs they want to run the TSan testsuite on.
  • +
  • #13014 (Miod Vallat, review by Nicolás Ojeda Bär) add per function sections support to the missing compiler backends: This PR is an example of how much focus there is on ensuring that each native backend is equally supported, having features available across all Tier-1 platforms. Here, the compile-time option function–sections was re-enabled on all previously unsupported (POWER, riscv64, and s390x) native backends.
  • +
  • #11996 emancipate dynlink from compilerlibs (Sébastien Hinderer and Stephen Dolan, review by Damien Doligez and Hugo Heuzard): The dynlink library used to depend on compilerlibs, having to embed a copy of compilerlibs meaning that it would be compiled twice, costing the user in time and performance. After the change, the build time and size of both dynlink.cma and dynlink.cmxawere reduced.
  • +
+

Miscellaneous Bug Fixes

+

These two bug fixes grew out of internship projects at Tarides, it's great to see how these projects can benefit the language as a whole.

+
    +
  • #13419 (B. Szilvasy and Nick Barnes, review by Miod Vallat, Nick Barnes, Tim McGilchrist, and Gabriel Scherer): This PR addressed resource leaks that caused memory bugs in the runtime events system.
  • +
  • #13535 (Antonin Décimo, Nick Barnes, report by Nikolaus Huber and Jan Midtgaard, review by Florian Angeletti, Anil Madhavapeddy, Gabriel Scherer, and Miod Vallat): Expanded the documentation for Hashtbl.create to explain that negative values are allowed in the hash table but will be disregarded.
  • +
+

These bug fixes stem from discoveries made during the release cycle of the 5.3 update. Catching and fixing broken bits of code is an important but often lengthy part of the release process.

+
    +
  • #13138 (Gabriel Scherer, review by Nick Roberts): This PR is an old one, first opened eight years ago in 2016! Optimised pattern matching with mutable and lazy patterns was observed to result in occasions where seemingly impossible cases were taken, causing unsoundness issues. After lengthy efforts to narrow down the cause, the problem has been fixed for 5.3!
  • +
  • #13519 (Sébastien Hinderer, report by William Hu, review by David Allsopp): This PR restored backward compatibility lost when renaming some items in Makefile.config.
  • +
  • #13591 (Antonin Décimo, review by Nick Barnes, report by Kate Deplaix): This PR fixed a problem whereby compiling C++ code using the OCaml C API resulted in a name-mangled caml_state on Cygwin. The fix ensured that installed headers were compatible with C++ and protected the ones that were not with CAML_INTERNALS.
  • +
  • #13471 (Florian Angeletti, review by Gabriel Scherer): Added a flag to define the list of keywords recognisable by the lexer, making adding future keywords to OCaml easier.
  • +
  • #13520 (David Allsopp, review by Sébastien Hinderer and Miod Vallat): Fixed the compilation of native-code versions of systhreads.
  • +
+

What’s Next?

+

Work on OCaml continues! The next few months will bring more features and bug fixes to the language, with focus on big changes like the relocatable compiler, unloadable runtime, and laying the ground work for project-wide renaming and other powerful navigation and refactoring features. The OCaml changelog is the place to go to keep up with what’s new, as well as the OCaml Discuss forum.

+

You can connect with us on Bluesky, X, Mastodon, Threads, and LinkedIn or sign up for our mailing list to stay updated on our latest projects. We look forward to hearing from you!

+ diff --git a/data/planet/tarides/ocaml-in-space-spaceos-is-on-a-satellite.md b/data/planet/tarides/ocaml-in-space-spaceos-is-on-a-satellite.md new file mode 100644 index 0000000000..b451115212 --- /dev/null +++ b/data/planet/tarides/ocaml-in-space-spaceos-is-on-a-satellite.md @@ -0,0 +1,25 @@ +--- +title: 'OCaml in Space: SpaceOS is on a Satellite!' +description: Our sister company Parsimoni sends OCaml into space aboard DPhi Space's + Clustergate ride-sharing platform to test the cababilities of SpaceOS. +url: https://tarides.com/blog/2025-04-03-ocaml-in-space-spaceos-is-on-a-satellite +date: 2025-04-03T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/rocket-launch-1360w.webp +authors: +- Tarides +source: +--- + +

OCaml is in space! With its impressive performance and security guarantees, OCaml is a great choice for the many interconnected devices that power our world. Satellites are not only crucial to the functioning of these devices, but the new generation of satellites are beginning to function like Cloud servers, where one device hosts more than one software and performs more than one service.

+

The natural next step, considering the growing need for agile multi-purpose satellites and the suitability of OCaml-based solutions, is to put OCaml to work in space! Following up on our sister company Parsimoni’s SpaceOS project, there has been an exciting development on this front. Parsimoni has partnered with DPhi Space and put SpaceOS software aboard their Clustergate ride-sharing platform for hosted payloads. OCaml launched into space aboard Transporter-13 on the 15th of March.

+

The Clustergate Platform

+

Clustergate is a payload platform developed by DPhi Space and deployed on a host satellite. The goal of this platform is to offer the power and computing capabilities of a larger satellite to cube-sat-sized payloads at a lower cost, where customers only pay for what they need. Making satellite deployment more accessible and agile will change the future of space innovation, incentivising new actors and services.

+

Parsimoni is changing the way that satellite software is designed, centring on the security, efficiency, and scalability of satellite payload management. By utilising unikernel technology written in OCaml, SpaceOS can host multiple applications with a reduced attack surface, safe from a multitude of common security vulnerabilities, without the overhead of typical virtual machines.

+

What’s on the Satellite?

+

DPhi Space has embedded its own Clustergate computer on Transporter-13, and the team behind SpaceOS has onboarded OCaml 5 software on the satellite. As part of a larger ‘rideshare’ mission, DPhi Space’s computer hosts a variety of software and hardware from different partners.

+

So, what OCaml code is on the satellite? All in all, the team have included a simple version of Petrel to manage unikernels, the necessary ‘glue code’ to give unikernels access to orbital data, the basic functionality needed to manage data transfers and send commands, plus a ‘hello world’ unikernel. Petrel is an experimental unikernel manager and orchestrator (written in OCaml 5 with Eio concurrency) based on Albatross by Robur. Instead of hardware virtualisation (which is not available on this flight), our team uses the solo5-spt backend of MirageOS as the unikernel runtime, which leverages Linux’s seccomp feature to isolate the software payloads.

+

During the mission, they will test whether the system works by sending new MirageOS unikernels using the data onboard. Parsimoni expects to start testing the software onboard in May. The goal is to show SpaceOS in action, sending and receiving interesting data and deploying self-contained applications on a limited bandwidth. They will start with the hello world and move on to more complex tasks utilising orbital data.

+

Until Next Time

+

You can watch the launch of Transporter-13 to see the moment when OCaml travels through the atmosphere! If you want to discuss the opportunities that SpaceOS offers for deploying specialised and secure applications that use limited resources efficiently, you can contact us or Parsimoni to find out more.

+

Connect with Tarides online on Bluesky, Mastodon, Threads, and LinkedIn or sign up for our mailing list to stay updated on our latest projects.

+ diff --git a/data/planet/tarides/tarides-2024-in-review.md b/data/planet/tarides/tarides-2024-in-review.md new file mode 100644 index 0000000000..adefa66ed6 --- /dev/null +++ b/data/planet/tarides/tarides-2024-in-review.md @@ -0,0 +1,544 @@ +--- +title: 'Tarides: 2024 in Review' +description: Tarides advanced OCaml in 2024 with the Dune Developer Preview, the first + stable multicore release, 8x WebAssembly boosts, and expanded Windows support. +url: https://tarides.com/blog/2025-01-20-tarides-2024-in-review +date: 2025-01-20T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/review-1360w.webp +authors: +- Tarides +source: +--- + +

At Tarides, we believe in making OCaml a +mainstream programming language by improving its tooling and +integration with other successful ecosystems. In 2024, we focused our +efforts on initiatives to advance this vision by addressing key +technical challenges and engaging with the community to build a +stronger foundation for OCaml’s growth. This report details our work, +the rationale behind our choices, and the impact achieved. We are very +interested in getting your feedback: please get in +touch (or respond to the +Discuss thread) +if you believe we are going in the right direction.

+

TL;DR – In 2024, Tarides focused on removing adoption friction with +better documentation and tools; and on improving adoption via the +integration with three key thriving ecosystems: multicore programming, +web development, and Windows support. Updates to +ocaml.org improved onboarding and documentation, +while the Dune Developer Preview +simplified workflows with integrated package management. Merlin added +support for project-wide reference +support +and odoc 3, +which is about to be released. OCaml 5.3 marked the first stable +multicore release, and js_of_ocaml achieved up to 8x performance +boosts in real-world commercial applications thanks to added support +for WebAssembly. On Windows, opam 2.2 brought full compatibility and +CI testing to all Tier 1 platforms on opam-repository, slowly moving +community packages towards reliable and better support for +Windows. Tarides’ community support included organising the first FUN +OCaml conference, many local meetups, and two +rounds of Outreachy internships.

+

Better Tools: Toward a 1-Click Installation of OCaml

+

Our primary effort in 2024 was to continue delivering on the OCaml +Platform roadmap published +last year. We focused on making it easier to get started with OCaml +by removing friction in the installation and onboarding process. Our +priorities were guided by the latest OCSF User +Survey, +direct user interviews, and +feedback gathered from +the OCaml community. Updates from Tarides and other OCaml Platform +maintainers were regularly shared in the OCaml Platform +Newsletter.

+

OCaml.org

+

OCaml.org is the main entry point for new users of OCaml. Tarides +engineers are key members of the OCaml.org team. Using +privacy-preserving analytics, +the team tracked visitor behaviour to identify key areas for +improvement. This led to a redesign of the installation +page, simplifying the setup process, and a +revamp of the guided tour of +OCaml to better introduce the +language. Both pages saw significant traffic increases compared to +2023, with the installation page recording 69k visits, the tour +reaching 65k visits and a very encouraging total number of visits +increasing by +33% between Q3 and Q4 2024

+

Average Monthly Visits

+

Efforts to improve user experience included a satisfaction survey +where 75% of respondents rated their experience positively, compared +to 17% for the previous version of the site. User testing sessions +with 21 participants provided further actionable insights, and these +findings informed updates to the platform. The redesign of OCaml.org +community sections was completed using this feedback. It introduced +several new features: a new Community landing +page, an academic institutions +page with course listings, and an +industrial users showcase. The +team also implemented an automated event +announcement system to inform the community +of ongoing activities.

+

Progress and updates were regularly shared through the OCaml.org +newsletters, +keeping the community informed about developments. Looking ahead, the +team will continue refining the platform by addressing feedback, +expanding resources, and monitoring impact through analytics to +support both new and experienced OCaml users. Lastly, the +infrastructure they build is starting to be used by other communities: +Rocq just announced their brand new +website, built using the same codebase as ocaml.org!

+

Dune as the Default Frontend of the OCaml Platform

+

One of the main goals of the OCaml Platform is to make it easier for +users—especially newcomers—to adopt OCaml and build projects with +minimal friction. A critical step toward this goal is having a single +CLI to serve as the frontend for the entire OCaml development +experience (codenamed +Bob in +the past). This year, we made significant progress in that direction +with the release of the Dune Developer +Preview.

+

Setting up an OCaml project currently requires multiple tools: opam +for package management, dune for builds, and additional +installations for tools like OCamlFormat or Odoc. While powerful, this +fragmented workflow can make onboarding daunting for new users. The +Dune Developer Preview consolidates these steps under a single CLI, +making OCaml more approachable. With this preview, setting up and +building a project is as simple as:

+
    +
  1. dune pkg lock to lock the dependencies.
  2. +
  3. dune build to fetch the dependencies and compile the project.
  4. +
+

This effort is also driving broader ecosystem improvements. The +current OCaml compiler relies on fixed installation paths, making it +difficult to cache and reuse across environments, so it cannot be +shared efficiently between projects. To address this, we are working +on making the compiler relocatable (ongoing +work). This change will enable +compiler caching, which means faster project startup times and fewer +rebuilds in CI. As part of this effort, we also +maintain +patches to core OCaml projects to make them relocatable – and we +worked with upstream to merge (like for +ocamlfind). Tarides +engineers also continued to maintain Dune and other key Platform +projects, ensuring stability and progress. This included organising +and participating in regular development meetings (for +Dune, +opam, +Merlin, +ppxlib, etc.) +to prioritise community needs and align efforts across tools like Dune +and opam to avoid overlapping functionality.

+

The Dune Developer Preview is an iterative experiment. Early user +feedback has been promising (the Preview’s NPS went from +9 in Q3 +2024 to +27 in Q4 2024), and future updates will refine the +experience further. We aim to ensure that experimental features in the +Preview are upstreamed into stable releases once thoroughly +tested. For instance, the package management feature is already in +Dune 3.17. We will announce and document it more widely when we believe +it is mature enough for broader adoption.

+

Editors

+

In 2024, Tarides focused on improving editor integration to lower +barriers for new OCaml developers and enhance the experience for +existing users. Editors are the primary way developers interact with +programming languages, making seamless integration essential for +adoption. With more than 73% of developers using Visual Studio Code +(VS +Code), +VS Code is particularly important to support, especially for new +developers and those transitioning to OCaml. As part of this effort, +Tarides wrote and maintained the official VS Code plugin for +OCaml, +prioritising feature development for this editor. We also support +other popular editors like Emacs and Vim—used by many Tarides +engineers—on a best-effort basis. Improvements to +OCaml-LSP and +Merlin, both maintained by Tarides, +benefit all supported editors, ensuring a consistent and productive +development experience.

+

Total VSCode Plugin Installation

+

While several plugins for OCaml exist (OCaml and Reason +IDE–128k +installs, +Hackwaly–90k +installs), our OCaml VS Code +plugin +–now with over 208k downloads– is a key entry point for developers +adopting OCaml in 2024. This year, we added integration with the Dune +Developer Preview, allowing users to leverage Dune's package +management and tooling directly from the editor. Features such as +real-time diagnostics, autocompletion, and the ability to fetch +dependencies and build projects without leaving VS Code simplify +development and make OCaml more accessible for newcomers.

+

The standout update in 2024 was the addition of project-wide +reference +support, +a long-requested feature from the OCaml community and a top priority +for commercial developers. This feature allows users to locate all +occurrences of a term across an entire codebase, making navigation and +refactoring significantly easier—especially in large +projects. Delivering this feature required coordinated updates across +the ecosystem, including changes to the OCaml compiler, Merlin, OCaml +LSP, Dune, and related tools. The impact is clear: faster navigation, +reduced cognitive overhead, and more efficient workflows when working +with complex projects.

+

Additional improvements included support for new Language Server +Protocol features, such as signature_help and inlay_hint, which +enhance code readability and provide more contextual +information. These updates enabled the introduction of new commands, +such as the "Destruct" command. This little-known but powerful +feature +automatically expands a variable into a pattern-matching expression +corresponding to its inferred type, streamlining tasks that would +otherwise be tedious.

+

+Destruct on expression +

+

Documentation

+

Documentation was identified as the number one pain point in the +latest OCSF +survey. It +is a critical step in the OCaml developer journey, particularly after +setting up the language and editor. Tarides prioritised improving +odoc to make it easier for developers to find information, learn the +language, and navigate the ecosystem effectively. High-quality +documentation and tools to help developers get "unstuck" are essential +to reducing friction and ensuring a smooth adoption experience.

+

Tarides is the primary contributor and maintainer of +odoc, OCaml’s main documentation +tool. In preparation for the odoc 3 +release, our +team introduced two significant updates. First, the odoc Search +Engine +was integrated, allowing developers to search directly within OCaml +documentation via the Learn page. Second, +the odoc +Cheatsheet +provides a concise reference for creating and consuming OCaml +documentation. We would like to believe that these updates, deployed +on ocaml.org, were the main cause of a 45% increase in package +documentation usage on +https://ocaml.org/pkg/ in Q4 2024!

+

Discussions and Documentations

+

Another area where developers often get stuck is debugging programs +that don’t work as expected. Alongside reading documentation, live +debuggers are crucial for understanding program issues. Tarides worked +to improve native debugging for OCaml, focusing on macOS, where LLDB +is the only supported debugger. Key progress included a name mangling +fix to improve symbol +resolution, restoring ARM64 backtraces, and introducing Python shims +for code sharing between LLDB and GDB.

+

OCaml’s error messages remain a common pain point, particularly for +syntax errors. Unlike Rust’s error +index, OCaml +does not (yet!) have a centralised repository of error +explanations. Instead, we are focused on making error messages more +self-explanatory. This requires developing new tools, such as +lrgrep, a domain-specific +language for analysing grammars built with Menhir. lrgrep enables +concise definitions of error cases, making it possible to identify and +address specific patterns in the parser more effectively. This +provides a practical way to improve error messages without requiring +changes to the compiler. In December 2024, @let-def successfully +defended his PhD (a collaboration between Inria and Tarides) on this +topic, so expect upstreaming work to start soon.

+

OCaml Package Ecosystem

+

The last piece of friction we aimed to remove in 2024 was ensuring +that users wouldn’t encounter errors when installing a package from +the community. This required catching issues early—before packages are +accepted into opam-repository and made available to the broader +ecosystem. To achieve this, Tarides has built and maintained extensive +CI infrastructure, developed tools to empower contributors, and guided +package authors to uphold the high quality of the OCaml package +ecosystem.

+

In 2024, Tarides’ CI infrastructure supported the OCaml community at +scale, handling approximately 20 million jobs on 68 machines +covering 5 hardware architectures. This infrastructure continuously +tested packages to ensure compatibility across a variety of platforms +and configurations, including OCaml’s Tier 1 platforms: x86, ARM, +RISC-V, s390x, and Power. It played a critical role during major +events, such as new OCaml releases, by validating the ecosystem’s +readiness and catching regressions before they impacted +users. Additionally, this infrastructure supported daily submissions +to opam-repository, enabling contributors to identify and resolve +issues early, reducing downstream problems. To improve transparency +and accessibility, we introduced a CI pipeline that automates +configuration updates, ensuring seamless deployments and allowing +external contributors to propose and apply changes independently.

+

In addition to maintaining the infrastructure, Tarides developed and +maintained the CI framework running on top of it. A major focus in +2024 was making CI checks available as standalone CLI tools +distributed via opam. These tools enable package authors to run +checks locally, empowering them to catch issues before submitting +their packages to opam-repository. This approach reduces reliance on +central infrastructure and allows developers to work more +efficiently. The CLI tools are also compatible with GitHub Actions, +allowing contributors to integrate tests into their own workflows. To +complement these efforts, we enhanced opam-repo-ci, which remains an +essential safety net for packages entering the repository. Integration +tests for linting and reverse dependencies were introduced, enabling +more robust regression detection and improving the reliability of the +ecosystem.

+

To uphold the high standards of the OCaml ecosystem, every package +submission to opam-repository is reviewed and validated to ensure it +meets quality criteria. This gatekeeping process minimises errors +users might encounter when installing community packages, enhancing +trust in the ecosystem. In 2024, Tarides continued to be actively +involved +in maintaining the repository, ensuring its smooth operation. We also +worked to guide new package authors by updating the contributing +guide +and creating a detailed +wiki with actionable +instructions for adding and maintaining packages. These resources were +announced on +Discuss +to reach the community and simplify the process for new contributors, +improving the overall quality of submissions.

+

Playing Better with the Larger Ecosystem

+

Concurrent & Parallel Programming in OCaml

+
+"Shared-memory multiprocessors have never really 'taken off', at +least in the general public. For large parallel computations, clusters +(distributed-memory systems) are the norm. For desktop use, +monoprocessors are plenty fast."
+ +

Twenty+ years after this statement, processors are multicore by +default, and OCaml has adapted to this reality. Thanks to the combined +efforts of the OCaml Labs and Tarides team, the OCaml 5.x series +introduced multicore support after a decade of research and +experimentation. +While this was a landmark achievement, the path to making multicore +OCaml stable, performant, and user-friendly has required significant +collaboration and continued work. In 2024, Tarides remained focused on +meeting the needs of the broader community and commercial users.

+

OCaml 5.3 (released last week) was an important milestone in this +journey. With companies such as Routine, +Hyper, and +Asemio +adopting OCaml 5.x, and advanced experimentation ongoing at Jane +Street, Tezos, Semgrep, and others, OCaml 5.3 is increasingly seen as +the first “stable” release of the multicore series. While some +performance issues +remain in specific parts of the runtime, we are working closely with +the community to address them in OCaml 5.4. Tarides contributed +extensively to the +5.2 +and +5.3 +releases by directly contributing to nearly two-thirds of the merged +pull requests. Since Multicore OCaml was incorporated upstream in +2023, we have been continuously involved in the compiler and language +evolution in collaboration with Inria and the broader OCaml ecosystem.

+

Developing correct concurrent and parallel software is inherently +challenging, and this applies as much to the runtime as to +applications built on it. In 2024, we focused on advanced testing +tools to help identify and address subtle issues in OCaml’s runtime +and libraries. The property-based test +suite reached +maturity this year, uncovering over 40 critical issues, with 28 +resolved by Tarides engineers. Trusted to detect subtle bugs, such as +issues with orphaned +ephemerons, +the suite has become an integral part of OCaml’s development +workflow. Importantly, it is accessible to contributors without deep +expertise in multicore programming, ensuring any changes in the +compiler or the runtime do not introduce subtle concurrency bugs.

+

A stacked histogram illustrating the outcome of CI workflow runs split, focusing only on the 'ci', 'genuine', and 'other' error categories

+

Another critical effort was extending ThreadSanitizer (TSAN) support +to most Tier 1 platforms and applying it extensively to find and fix +data races in the +runtime. This +work has improved the safety and reliability of OCaml’s multicore +features and is now part of the standard testing process, further +ensuring the robustness of the runtime.

+

Beyond testing, we also worked to enhance library support for +multicore programming. The release of the Saturn +library +introduced lock-free data structures tailored for OCaml 5.x. To +validate these structures, we developed +DSCheck, +a static analyser for verifying lock-free algorithms. These tools, +along with Saturn itself, provide developers with reliable building +blocks for scalable multicore applications.

+

Another promising development in 2024 was the introduction of the +Picos +framework. Picos aims to provide a low-level foundation for +concurrency, simplifying interoperability between libraries like Eio, +Moonpool, Miou, Riot, Affect, etc. Picos offers a simple, +unopinionated, and safe abstraction layer for concurrency. We believe +it can potentially standardise concurrency patterns in OCaml, but we +are not there yet. Discussions are underway to integrate parts of +Picos into higher-level libraries and, eventually, the standard +library. We still have a long way to go, and getting feedback from +people who actively tried it in production settings would be very +helpful!

+

Web

+

Web development remains one of the most visible and impactful domains +for programming languages; JavaScript, HTML, and CSS are the most +popular +technologies +in 2024. For OCaml to grow, it must integrate well with this +ecosystem. Fortunately, the OCaml community has already built a solid +foundation for web development!

+

On the frontend side, in 2024, Tarides focused on strengthening key +tools like js_of_ocaml +by expanding its support for WebAssembly +(Wasm). js_of_ocaml (JSOO) has long been the backbone of OCaml’s web +ecosystem, enabling developers to compile OCaml bytecode into +JavaScript. This year, we merged Wasm support back into +JSOO, unifying the +toolchain and simplifying adoption for developers. The performance +gain of Wasm has been very impressive so far: CPU-intensive +applications in commercial settings have seen 2x to 8x speedups +using Wasm compared to traditional JSOO. We also worked on better +support for effect handlers in js_of_ocaml to ensure applications +built with OCaml 5 can run as fast in the browser as they used to with +OCaml 4.

+

On the backend side, Tarides maintained and contributed to Dream, a +lightweight and flexible web framework. Dream powers projects like +our own website and the +MirageOS website, where we maintain a fork to make +Dream and MirageOS work well together. Additionally, in 2024, we +enhanced cohttp, adding proxy +support to address +modern HTTP requirements.

+

While Tarides focused on JSOO, wasm_of_ocaml, Dream, and Cohttp, the +broader community made significant strides elsewhere. Tools like +Melange offer an alternative for compiling OCaml to JavaScript, and +frameworks like Ocsigen, which integrates backend and frontend +programming, continue to push the boundaries of what’s possible with +OCaml on the web. Notably, Tarides will build on this momentum in 2025 +through a grant to +improve direct-style programming for Ocsigen.

+

Windows

+

Windows is the most widely used operating system, making first-class +support for it critical to OCaml’s growth. In 2024, 31% of visitors +to ocaml.org accessed the site from Windows, +yet the platform’s support historically lagged behind Linux and +macOS. This gap created barriers for both newcomers and commercial +users. We saw these challenges firsthand, with Outreachy interns +struggling to get started due to tooling issues, and commercial users +reporting difficulties with workflow reliability and compilation +speed.

+

To address these pain points, Tarides, in collaboration with the OCaml +community, launched the Windows Working +Group. A +key milestone that our team contributed to was the release this year +of opam 2.2, three years after its predecessor. This release made +the upstream opam-repository fully compatible with Windows for the +first time, removing the need for a separate repository and providing +Windows developers access to the same ecosystem as Linux and macOS +users. The impact has been clear: feedback on the updated installation +workflow has been overwhelmingly positive, with developers reporting +that it "just works." The install page +for Windows is now significantly shorter and simpler!

+

In the OCaml 5.3 release, Tarides restored the MSVC Windows port, +ensuring native compatibility and improving performance for Windows +users. To further support the ecosystem, Tarides added Windows +machines to the opam infrastructure, enabling automated testing for +Windows compatibility on every new package submitted to opam. This has +already started to improve package support, with ongoing fixes from +Tarides and the community. The results are publicly visible at +windows.check.ci.dev, which we run on +our infrastructure, providing transparency and a way to track progress +on the status of our ecosystem. While package support is not yet on +par with other platforms, we believe that the foundations laid in +2024—simplified installation, improved tooling, and continuous package +testing—represent a significant step forward.

+

Community Engagement and Outreach

+

In 2024, Tarides contributed to building a stronger OCaml community +through events, internships, and support for foundational +projects. The creation of FUN OCaml 2024 in +Berlin was the first dedicated OCaml-only event for a long time +(similar to how the OCaml Workshop was separated from ICFP in the +past). Over 75 participants joined for two days of talks, workshops, +and hacking, and the event has already reached 5k+ views on +YouTube. Tarides +also co-chaired the OCaml Workshop at ICFP +2024 in Milan, bringing together +contributors from academia, industry, and open-source +communities. These events brought together two different kinds of +OCaml developers (with some overlap), bringing an interesting energy +to our community.

+

To expand local community involvement, Tarides organised OCaml hacking +meetups in +Manila +and +Chennai. To +make it easier for others to host similar events, we curated a list of +interesting hacking issues from past Cambridge +sessions, +now available on +GitHub.

+

As part of the Outreachy program, Tarides supported two rounds of +internships in 2024, with results published on +Discuss and +watch.ocaml.org. These internships not only +provided great contributions to our ecosystem but also brought fresh +insights into the challenges faced by new users. For example, interns +identified key areas where documentation and tooling could be +improved, directly informing future updates.

+

Tarides also maintained its commitment to funding critical open-source +projects and maintainers. We continued funding +Robur for their +maintenance work on MirageOS (most of those libraries are used by many +–including us– even in non-MirageOS context) and Daniel +Bünzli, whose libraries like +cmdliner are essential for some of our development.

+

Finally, Tarides extended sponsorships to non-OCaml-specific events, +including JFLA, +BobConf, +FSTTCS, and Terminal +Feud (which garnered +over 100k views). These events expanded OCaml’s visibility to new +audiences and contexts, introducing the language to a broader +technical community that –we hope– will discover OCaml and enjoy using +it as much as we do.

+

What’s Next?

+

As we begin 2025, Tarides remains committed to making OCaml a +mainstream language. Our focus this year is to position OCaml as a +robust choice for mission-critical applications by enhancing developer +experience, ecosystem integration, and readiness for high-assurance +use cases.

+

We aim to build on the Dune Developer Preview to further improve +usability across all platforms, with a particular emphasis on Windows, +to make OCaml more accessible to a broader range of +developers. Simultaneously, we will ensure OCaml is ready for critical +applications in industries where reliability, performance, and +security are essential. Projects like +SpaceOS +showcase the potential of memory- and type-safe languages for +safety-critical systems. Built on MirageOS and OCaml’s +unique properties, SpaceOS is part of the EU-funded +Orchide project and aims to set a new +standard for edge computing in space. Additionally, SpaceOS is being +launched in the US through our spin-off +Parsimoni. However, these needs are not +limited to Space: both the EU Cyber Resilience +Act +and the US cybersecurity +initiatives +highlight the growing demand for type-safe, high-assurance software to +address compliance and security challenges in sensitive +domains. Tarides believes that OCaml has a decisive role to play here +in 2025!

+

I’d like to personally thank our sponsors and customers, especially +Jane Street, for their unwavering support over the years, and to +Dennis Dang, our single recurring +GitHub sponsor. Finally, to every member of Tarides who worked so hard +in 2024 to make all of this happen: thank you. I’m truly lucky to be +sailing with you on this journey!

+

We are looking for sponsors on +GitHub, are happy to +collaborate on innovative projects +involving OCaml or MirageOS and offer commercial +services for open-source projects – +including long-term support, development of new tools, or assistance +with porting projects to OCaml 5 or Windows.

+ diff --git a/data/planet/tarides/tarides-at-bob-konferenz-2025.md b/data/planet/tarides/tarides-at-bob-konferenz-2025.md new file mode 100644 index 0000000000..4ca000e4f3 --- /dev/null +++ b/data/planet/tarides/tarides-at-bob-konferenz-2025.md @@ -0,0 +1,129 @@ +--- +title: Tarides at BOB Konferenz 2025 +description: We were present at BOBKonf 2025, as speakers and attendees! Here's a + brief report on our experiences in Berlin. +url: https://tarides.com/blog/2025-05-08-tarides-at-bob-konferenz-2025 +date: 2025-05-08T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/heart-berlin-1360w.webp +authors: +- Tarides +source: +--- + +

BOB Konferenz is a 10-year-old +conference whose tagline is: "The software development +conference for everyone dissatisfied with the status quo"! Indeed, +BOB is a conference that focusses on a variety of subjects that +strongly converge with the interests of Tarides (and the OCaml world +in general). It aims to cover topics such as functional programming, +"fancy types" (dependent types, gradual typing, linear types, ...), +formal methods for correctness and robustness, abstractions for +concurrency and parallelism, controlled side effects, next-generation +IDEs, and much more!

+

The convergence has been so strong that, over the years, some big +names from the OCaml community have shown up — like Anil +Madhavapeddy, Hannes +Mehnert, Gabriel +Scherer, and even Xavier +Leroy! This is one of the many reasons why +Tarides decided to sponsor the 2024 +edition and send Sabine +Schmaltz and Leandro +Ostera.

+

For the 2025 edition, March 14, 2025, in Berlin, Xavier Van de +Woestyne had the privilege of presenting Tarides’ +work on editor support for OCaml during his talk "Beyond the Basics +of LSP: Advanced IDE Services for +OCaml." Accompanied by +Antonin Decimo, who attended the +conference, Xavier travelled to BOBKonf 2025 to share their insights and +experience.

+

A Wide Range of Interesting Talks

+

The BOB program is wonderfully eclectic, and every talk is an +opportunity to discover something new! For example, after a keynote on +Local-First software — which +included many fascinating use cases with potential applications for +Irmin. We had the chance to attend talks on +abstraction, speculative +reasoning about functions based on their types (for instance, a +function of type a -> a having only one possible inhabitant), the +application of separation logic for concurrency in +Idris, and even collaborations +between engineers and mathematicians on the specification of formal +methods.

+

We explored the functional programming counterpart to design +patterns — with a strong +emphasis on the power of robust module systems, something that +deeply resonates with us as OCaml developers. That was followed by a +deep reflection on object-oriented programming from a functional +programmer’s perspective, a clear +explanation of how recursive definitions work in +Lean, and, to wrap it all up, +a guide to common pitfalls to avoid when building distributed systems +with microservices.

+

All in all, it was an intense and inspiring day — packed with ideas +that strongly resonated with us. From our perspective, the themes +explored throughout the conference aligned closely with the +ideological and technical choices we’ve made at Tarides, particularly +our commitment to OCaml. But beyond that, many of the talks echoed the +challenges and directions of the projects we actively maintain!

+

About our Presentation

+

Although the goal of our +presentation (you can watch the recording on BOBKonf's website) was to +discuss OCaml editor support (through +Merlin, +Ocaml-lsp-server, and its +clients, Visual Studio +Code and +Emacs), we aimed to present +an approach and a set of features that wouldn’t limit our audience to +just OCaml users. Instead, we wanted to spark a conversation with +other IDE users/maintainers to share ideas and implementation +perspectives!

+

We believe the presentation was well-received, generating some very +interesting questions along with positive conversations about how +some of the ideas we presented could be applied to proof assistants +like Isabelle, +Idris2, and +Agda.

+

There was a proposal to combine our efforts to improve the Language +Server +Protocol, +making it even more welcoming for certain functional languages that +leverage interactive features (where the acceptance model is primarily +based on voting). From our perspective, these were excellent and +motivating responses!

+

Meet and Greet

+

Beyond the technical side, one of the great things about conferences +is the chance to meet people—catch up with familiar faces, make new +connections, and have meaningful conversations around topics we’re all +passionate about! From our perspective, even though the schedule is +quite packed, the talk slots are spaced out just enough to let us +catch our breath — but more importantly, to connect and chat with +members of the community. It really helps to foster a friendly, sociable +atmosphere!

+

To Conclude

+

Attending conferences is an integral part of our work as engineers—for +several important reasons:

+
    +
  • Keeping up with the latest in technology and research
  • +
  • Sharing our progress and presenting the work we’ve been doing
  • +
  • Initiating potential collaborations with people driven by similar +goals and motivations.
  • +
+

So yes, it's important — but at conferences like BOB, it’s also a real +pleasure! The talks are truly fascinating (we’re already looking +forward to the video recordings so we can catch up on what we missed), +and the interactions are incredibly motivating for our work. If, like +us, you’re interested in functional programming, fancy types, formal +methods, and many other exciting topics, don’t hesitate to check out +BOB’s YouTube channel – +and maybe even consider attending next time!

+
+

Connect with Tarides online on +Bluesky, +Mastodon, +Threads, and +LinkedIn or sign up for +our mailing list to stay updated on our latest projects.

+ diff --git a/data/planet/tarides/the-first-wasmofocaml-release-is-out.md b/data/planet/tarides/the-first-wasmofocaml-release-is-out.md new file mode 100644 index 0000000000..20d48394eb --- /dev/null +++ b/data/planet/tarides/the-first-wasmofocaml-release-is-out.md @@ -0,0 +1,44 @@ +--- +title: The First Wasm_of_ocaml Release is Out! +description: "Discover what's new with the release of Js_of_ocaml 6.0.1 \u2013 including + Wasm support!" +url: https://tarides.com/blog/2025-02-19-the-first-wasm-of-ocaml-release-is-out +date: 2025-02-19T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/helloworld-1360w.webp +authors: +- Tarides +source: +--- + +

The first feature-complete release of Wasm_of_OCaml (also known as WSOO) is out! A low-level virtual machine and portable compilation target, Wasm is popular with many developers thanks to its flexibility and wide compatibility.

+

We introduced you to Wasm and the benefits of bringing support for it to OCaml in our blog post on it in 2023. Since then, Wasm_of_ocaml has undergone new developments, so let’s take a look at what’s new and give you an overview of the release.

+

What is Wasm_of_ocaml?

+

Let’s start with a quick recap. Wasm_of_ocaml is a fork of the popular Js_of_ocaml compiler, translating OCaml bytecode to WebAssembly. It is web-oriented and relies on a JavaScript environment, and is designed to be an alternative to Js_of_ocaml. Since WebAssembly provides a sandboxed environment and enforces memory safety it is well-suited for security-critical applications, such as blockchain applications and programs running in the cloud. We plan to target these environments in the future.

+

Wasm_of_ocaml builds on the WebAssembly garbage collection extension (WasmGC), which is available by default on Chrome, Safari, and Firefox. This design means we don’t need to reimplement a garbage collector, and - as an added benefit - gives us good interoperability with JavaScript. Js_of_ocaml translates OCaml bytecode to JavaScript and is a well-liked, industrial-strength compiler for running OCaml on the web. The goal of Wasm_of_ocaml’s development is to retain the strengths of Js_of_ocaml and offer feature parity and inter-compatibility between the two compilers. You can compile your programs with Wasm_of_ocaml instead of Js_of_ocaml (you may have to make a few adjustments) and experience overall better performance.

+

Because of its popularity and versatility, creating an OCaml to Wasm translator has been a big priority for the team, and they continue to improve and optimise Wasm_of_ocaml over time.

+

What’s New?

+

Over the past year, much work has been done to get Wasm_of_ocaml to release readiness. Some of the changes include:

+
    +
  • Putting Wasm_of_ocaml into the same development repo as Js_of_ocaml: This was a natural step due to how much code the two tools share, considering Wasm_of_ocaml is a fork of Js_of_ocaml. However, the two have diverged since the former was forked away from Js_of_ocaml. To put them in the same repo required changes to bring them back in sync. This change was necessary for the first public release of Wasm_of_ocaml, and you can check out the work in the associated PR.
  • +
  • Support for Wasm_of_ocaml in Dune: An important milestone on the road to the public release, this change allowed users to compile Wasm in Dune, making it much easier for existing OCaml projects to adopt the new tool. Wasm_of_ocaml support has been released in Dune 3.17.0, which you can upgrade to if you haven’t already.
  • +
  • Separate compilation: Support for separate compilation enables much faster compilation when building a program. There are two PRs: the first PR brings the main update, and the second PR makes it more fine-grained and avoids having to load too many modules.
  • +
  • Sourcemap support: PR #27 introduces support for source-level debugging of Wasm executables, implementing mapping between source and Wasm locations.
  • +
  • Support the JS String Builtins Extension: PR #33 change enables the use of JS string builtins when available for JS engines, which allows for more efficient operations on strings.
  • +
  • Minimise the use of the unsafe JS command eval: The JS command eval is known for being unsafe, and PR #24 creates an alternative workflow that minimises its use. Instead of using eval, strings can be emitted as external JavaScript fragments whenever the value of the string is known at compile time.
  • +
  • Store long-lived top-level values into global variables: PR #30 introduces a change where any variable that is used a number of instructions after being defined is stored as a global variable rather than a local variable. This change improves performance and reduces the compilation time of Wasm projects.
  • +
  • Updates to make Wasm_of_ocaml compatible with OCaml 5.2 and 5.3: Two PRs, #54 and #59, brought changes that made Wasm_of_ocaml compatible with OCaml: 5.2. For 5.3, PR #136 included updates to make Wasm_of_ocaml compatible with the then latest OCaml update.
  • +
  • Bugfixes: Let’s round off with some bug fixes! PR #22 ensured that locals are always explicitly initialised before being used, PR #31 fixed the spec-compliance of some emitted tuple instructions, and PR #46 fixed a stack resizing bug in structural value comparison.
  • +
+

These are just a subset of all the fixes and contributions, and I recommend that you explore the Wasm_of_ocaml repo for a more complete picture.

+

Benchmarks and Performance

+

The team has run several benchmarks with exciting results. When comparing the performance of Wasm_of_ocaml to Js_of_ocaml and the native code of OCaml’s compiler ocamlopt, the results consistently show that programs compiled with Wasm_of_ocaml are faster than ones compiled with Js_of_ocaml (but two times slower than native code). This holds true not only for microbenchmarks but on macroscopic benchmarks as well. Even more impressively, Jane Street reports that they have observed 2x-8x performance improvements using Wasm_of_ocaml compared to Js_of_ocaml.

+

Another aspect of performance lies in casts and bound checks. Wasm_of_ocaml uses a generic representation of values, which means that, at run time, a number of casts might be required to ensure safety. Furthermore, due to the nature of the data representation the team has chosen, a bound check is required whenever a field of value is accessed. The team found that the Wasm_of_ocaml checks take up around 10% of the execution overtime on the V8 engine and 20% on the Bonsai benchmark. The goal is to keep improving performance by reducing the amount of needless casts.

+

Regarding file size, Wasm_of_ocaml output code takes up more space than Js_of_ocaml, which is likely due to Wasm being a lower-level language than JavaScript. For example, Wasm_of_ocaml has to generate explicit code to allocate closures and access the environment, both implicit in JavaScript.

+

If you’re curious to learn more about Wasm_of_ocaml’s benchmarks and performance, Jérôme Vouillon’s talk from the ML track at ICFP 2024 goes more in-depth.

+

Release process, Plus a New Version of js_of_ocaml

+

From now on, wasm_of_ocaml and js_of_ocaml will be released jointly. For this reason, this first public release of wasm_of_ocaml is numbered 6.0.1 since it is synchronised with the release of js_of_ocaml 6.0.1.

+

A new and important feature of js_of_ocaml 6.0.0 is double translation, a way of making programs that use effect handlers faster. Effect handler support is realised by compiling some functions to Javascript code in continuation passing-style (CPS), which incurs a performance penalty. By passing --effects=double-translation, some functions are compiled in several versions, and the choice of which version of the function to run is made at run time. This improves performance at the cost of slightly larger Javascript bundles. More details are available on the effect handlers page of the js_of_ocaml manual.

+

Until Next Time

+

If you try Wasm_of_ocaml yourself and have any feedback or questions, please see our post on Discuss. You can also create issues in the Wasm_of_ocaml repo if you spot something that can be improved.

+

Connect with Tarides online on Bluesky, X, Mastodon, Threads, and LinkedIn or sign up for our mailing list to stay updated on our latest projects.

+ diff --git a/data/planet/tarides/the-ocaml-52-release-features-and-fixes.md b/data/planet/tarides/the-ocaml-52-release-features-and-fixes.md index 90a00c754b..9ca1de1283 100644 --- a/data/planet/tarides/the-ocaml-52-release-features-and-fixes.md +++ b/data/planet/tarides/the-ocaml-52-release-features-and-fixes.md @@ -51,7 +51,7 @@ source:

Preparing for Upcoming Features

Part of the contributions to each release focus on preparing the way for future features. 5.2 lays the foundation for some long-anticipated additions including:

    -
  • Project-Wide Occurrences: Ulysse Gérard's PR #12508 provides the required steps to support project-wide-occurences in OCaml projects, a feature that many Merlin users in particular have been waiting for. Work is ongoing to implement this in Merlin to enhance code navigation and refactoring. This change is possible thanks to OCaml's Shapes feature.
  • +
  • Project-Wide Occurrences: Ulysse Gérard's PR #12508 provides the required steps to support project-wide-occurrences in OCaml projects, a feature that many Merlin users in particular have been waiting for. Work is ongoing to implement this in Merlin to enhance code navigation and refactoring. This change is possible thanks to OCaml's Shapes feature.
  • Statmemprof: Statmemprof is a well-loved statistical memory profiler that was removed from OCaml before the multicore 5.0 release, due to unanswered questions about how it would perform. Significant efforts have gone into bringing statmemprof back, and 5.2 prepares the way in two PRs. PR #11911 features much of the initial conversation and collaboration to bring the feature back, and Nick Barnes's #12381 PR changes part of the memory profiler’s API to prepare it for multicore. This feature is expected to be included in 5.3 this autumn.
  • MSVC: MSVC is Microsoft's C/C++ compiler and users can compile OCaml 4.14 with MSVC. However, in OCaml 5.0 the runtime uses C features that MSVC doesn't support, making it incompatible with MSVC. Antonin Décimo's PR #12769 unifies MSVC and MinGW-w64 code paths to prepare for full MSVC support for OCaml 5, also expected to be re-introduced in OCaml 5.3 later this autumn.
diff --git a/data/planet/tarides/using-clang-cl-with-ocaml-5.md b/data/planet/tarides/using-clang-cl-with-ocaml-5.md new file mode 100644 index 0000000000..3596d89be5 --- /dev/null +++ b/data/planet/tarides/using-clang-cl-with-ocaml-5.md @@ -0,0 +1,30 @@ +--- +title: Using `clang-cl` With OCaml 5 +description: Antonin shares his findings from building OCaml 5 with Clang-cl during + the MSVC port restoration project, part of the effort to improve OCaml on Windows! +url: https://tarides.com/blog/2025-01-15-using-clang-cl-with-ocaml-5 +date: 2025-01-15T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/clang-cl-1360w.webp +authors: +- Tarides +source: +--- + +

Bringing new features to OCaml is not a trivial procedure, and any new contribution is subject to rigorous testing and inspection. The introduction of Multicore OCaml added a whole new dimension of complexity to the process, and this post takes you behind-the-scenes of a project that sprang from troubleshooting the restoration of MSVC to OCaml 5.

+

Motivation

+

OCaml 5.3 is released and comes with a restored MSVC (Microsoft Visual C/C++ compiler) port. It had been removed with the introduction of the multicore runtime in OCaml 5.0. The Restore the MSVC port of OCaml #12954 PR lists all the prerequisite changes, and the final streak of changes, required to restore support.

+

The OCaml 5 runtime requires C11 atomic support from the C compiler, which for MSVC was introduced in Visual Studio 2022 version 17.5 Preview 2. This early version had a few bugs during code generation and we were wondering if they would impact the OCaml runtime (fortunately, they did not). While the Microsoft team worked hard to fix the bugs, we learned about clang-cl, a driver program for Clang that attempts to be compatible with MSVC's cl.exe. It is ABI-compatible with MSVC, implements all MSVC compiler extensions, and is also a drop-in command-line replacement for cl.exe.

+

I wanted to try building OCaml with clang-cl, mostly because it would get us a second compiler's opinion on our code, as Clang has a different set of warnings and hints than MSVC. Seeing that clang-cl was already used to build Chrome and Firefox (1, 2), I was hoping the needs of the OCaml runtime would have already been covered and bugs fixed, and that we could adopt it seamlessly.

+

The OCaml 5 runtime uses the POSIX threads (pthreads) library on Unix-like systems for all its concurrency primitives. For the OCaml 5.3 branch we've chosen to use the winpthreads library, part of the MinGW-w64 project, which implements pthreads on Windows. The OCaml 5 MinGW-w64 port uses it, and we found out we could use it with MSVC too. I then submitted two patch series to winpthreads (Patches and cleanups towards MSVC support, MSVC support without GCC extensions), checking my work with MinGW-w64+GCC, MinGW-w64+clang, MSVC, and clang-cl, foreshadowing their use within the OCaml runtime. What an adventure! And thanks to the MinGW-w64 team for reviewing this work.

+

Using clang-cl

+

Clang on Unix-like systems masquerades as GCC, supports all GNU C extensions and defines the __GNUC__ macro. On Windows, it masquerades as MSVC and defines the _MSC_VER macro instead, but still supports the GNU C extensions that we can take advantage of!

+

The build system only required a few changes. For instance, MSVC currently defaults to C99 and needs two flags to switch to C11 and enable experimental C11 atomic support, whereas clang-cl defaults to C17. We also discussed how to improve the support of MSVC in Autoconf, which led to a few patches. We could then use clang-cl to discover new problems reported by the warnings it raised and fix them. In conjunction with this work, I raised the warning level of MSVC on the OCaml runtime C code from none to -W2.

+

Fortunately, most of the warnings were quite minor (see #13081 and #13243), mainly consisting of warnings for deprecated functions or implicit truncations when converting integers or floating points values of different sizes. Switching to newer compilers also allowed us to remove dead code and workarounds for older versions of the compilers.

+

I found out that most of the uses of compiler attributes or builtins were guarded by the __GNUC__ macro, and as such were only enabled by GCC or Clang on Unix, even though clang-cl on Windows supports them too. Compiler attributes may enable more checks and warnings from the compiler. For instance, the format attribute tags a function to be printf-like and checks the types of the list of values passed to it against the specifiers inside a format string. Compiler builtins may enable more optimisations, such as __builtin_expect. So, instead of guarding their use, we could discover whether the compiler provides them using newer macros such as __has_attribute or __has_builtin. This improved feature parity between the clang-cl port and an OCaml build using GCC or Clang.

+

In particular, we could detect the labels as values (also known as computed gotos) compiler extension to enable threaded code interpretation, which dramatically improves the speed of ocamlc, the OCaml bytecode interpreter. This optimisation isn't supported by MSVC and would require us to use inline assembly on x86 or write part of the bytecode interpreter in assembly on other architectures. If you're often using the bytecode interpreter, there's now a clear advantage of using clang-cl over MSVC. Another interesting optimisation uses software prefetching to speed up the GC when traversing the graph of values. We had worked on restoring it in OCaml 5 from OCaml 4 but forgot to port it to Windows!

+

The overall work on restoring the MSVC port of OCaml and also building it with clang-cl led to a few bug reports to Microsoft and to the LLVM project, which I hope will benefit the community. The OCaml project now has an extra set of compiler eyes that scrutinise each and every change on Windows. Windows users may now take advantage of a (compliant) C11 and C23 FOSS compiler, with a wide range of optimisations and checks available.

+

I'm grateful to my colleagues at Tarides for helping me with this work, the OCaml core team for reviewing it, and Jane Street for sponsoring this effort.

+

Try it Out and Stay in Touch!

+

With the release of opam 2.2 (now 2.3) supporting Windows, the restoration of the Cygwin port in OCaml 5.1, the MSVC port in OCaml 5.3, and the option to build OCaml with clang-cl, and the swarm of bug fixes that accompanied them, using OCaml on Windows has never been easier! Give it a whirl!

+

Connect with Tarides online on Bluesky, X, Mastodon, Threads, and LinkedIn or sign up for our mailing list to stay updated on our latest projects.

+ diff --git a/data/planet/tarides/were-moving-ocsigen-from-lwt-to-eio.md b/data/planet/tarides/were-moving-ocsigen-from-lwt-to-eio.md new file mode 100644 index 0000000000..8332b966e1 --- /dev/null +++ b/data/planet/tarides/were-moving-ocsigen-from-lwt-to-eio.md @@ -0,0 +1,41 @@ +--- +title: We're Moving Ocsigen from Lwt to Eio! +description: Announcing a new project transitioning the web development framework + Ocsigen from Lwt to Eio and effects, creating new tools and workflows. +url: https://tarides.com/blog/2025-03-13-we-re-moving-ocsigen-from-lwt-to-eio +date: 2025-03-13T00:00:00-00:00 +preview_image: https://tarides.com/blog/images/3dwebapps-1360w.webp +authors: +- Tarides +source: +--- + +

Among the big changes that came with OCaml 5, concurrency via effect handlers was introduced alongside the I/O library Eio, letting users take advantage of effects to write more efficient concurrent programs. In an exciting new project, we are transitioning one of the biggest OCaml open source projects, Ocsigen, from Lwt concurrency to concurrency using effects.

+

The most exciting part of this project is that we will develop tools to automate parts of the transition and document how we achieve it, which will be great resources for the wider OCaml community. This work is made possible thanks to a grant from the NLnet Foundation, which funds research and development projects furthering internet technologies and the open internet, and the NGI Zero Core fund of the European commission. This post will give you an overview of the tools, the goals of the project, and some of the methods we will use.

+

Why Ocsigen and Why Eio?

+

Ocsigen is a web and mobile framework composed of several projects and libraries including Eliom, Js_of_ocaml, Ocsigen Server, and Lwt. Ocsigen lets you build a variety of applications, from simple server-side web sites to complex client-server web and mobile apps. It is built using OCaml and benefits from its strong type system to reduce development time, simplify refactoring, and reduce the likelihood of bugs. It is one of the biggest open source projects in OCaml, and is used commercially to run the BeSport app.

+

Choosing a large and established project like Ocsigen will give the community a well-documented proof-of-concept of what the transition between different concurrency models looks like.

+

Lwt, a monadic-style concurrent programming library for OCaml, is developed as part of the Ocsigen umbrella. It has served as a way of managing I/O operations using promises for many different OCaml projects, and it is significant that Lwt’s own inventor and biggest user Ocsigen is now making the switch to effects.

+

The monadic style has several advantages over more traditional concurrency models (like preemptive threading or interaction loops) including fewer data races and straightforward writing, but also comes with drawbacks in comparison to direct-style effects-based concurrency. Namely, creating an abundance of heap allocations and introducing the function colouring problem to the user’s programs. With direct-style concurrency it is possible to write code in a natural, direct, style as opposed to callback-style with considerations for which code is concurrent and which is not. For more information about concurrency using effect handlers, check out our blog post on Eio.

+

Switching to effects is also a first step towards enabling the use of multicore features, which is not fully possible with Lwt.

+

Goals of the Project

+

The aim of the project is to create a straight-forward path for developers who want to transition projects to OCaml 5 and its new direct-style concurrency libraries. To this end, the team will develop tools for rewriting monadic syntax into direct style, rewrite interfaces, and automate the use of libraries like picos-lwt and eio-lwt. They will also develop heuristics for detecting places in the code where manual intervention is required, simplifying the developer workflow.

+

Put simply, we are going to:

+
    +
  • Automate the aspects of transforming monadic style concurrency to direct style concurrency that we can,
  • +
  • Make manual intervention as smooth as possible,
  • +
  • Document the process so that it is easy to replicate, troubleshoot, and adapt for other projects.
  • +
+

Making effects-based concurrency easier to adopt means that more OCaml developers can potentially take advantage of its benefits. Speaking from experience, Simon Grondin summed up his experiments with Eio in our interview with him from 2024:

+
+

Eio helped me reason about my code, and I discovered bugs and problems because of how much Eio had cleaned up the code. I uncovered hidden bugs in every program I converted from Lwt to Eio. Every single one also ended up being faster, not because Eio itself was faster (it was as fast as Lwt), but because of the optimisations I could now afford to make, thanks to the reduced complexity.

+
+

This project will enable more people to try Eio and see if their experience matches Simon’s, with the potential to significantly improve their workflow!

+

Challenges and Methods

+

One of the biggest challenges facing this work is the way that in an effect-based library there is an explicit fork feature to create a new thread, whereas forking is implicit with Lwt which makes it hard to detect. This fact alone is the reason why the team won’t be able to write a fully automated conversion tool.

+

Another challenge for the team is to make sure that they stay as neutral as possible in their approach to the effect library's design, in order to be able to make changes later or provide multiple alternatives.

+

Finally, they will strive to maintain backward compatibility to the greatest extent, by using Lwt-effect bridges to enable intercompatibility for existing applications without forcing them to switch immediately.

+

Until Next Time

+

Keep your eye on our blog and OCaml Discuss for more updates on this project and the tools that emerge from it.

+

Connect with Tarides online on Bluesky, Mastodon, Threads, and LinkedIn or sign up for our mailing list to stay updated on our latest projects.

+ diff --git a/data/releases/5.1.0.md b/data/releases/5.1.0.md index 2626572dc8..0a6abaa694 100644 --- a/data/releases/5.1.0.md +++ b/data/releases/5.1.0.md @@ -186,7 +186,7 @@ This is the `Seq.find_mapi`, `Seq.find_index`, `Array.find_mapi`, `Array.find_index`, `Float.Array.find_opt`, `Float.Array.find_index`, `Float.Array.find_map`, `Float.Array.find_mapi`. - (Sima Kinsart, review by Daniel Bünzli and Nicolás Ojeda Bär) + (T. Kinsart, review by Daniel Bünzli and Nicolás Ojeda Bär) - [#11410](https://github.com/ocaml/ocaml/issues/11410): Add Set.to_list, Map.to_list, Map.of_list, `Map.add_to_list: key -> 'a -> 'a list t -> 'a list t`. diff --git a/data/releases/5.2.0.md b/data/releases/5.2.0.md index 78908b324b..2504a6bb1e 100644 --- a/data/releases/5.2.0.md +++ b/data/releases/5.2.0.md @@ -14,7 +14,7 @@ highlights: | - Thread sanitiser support - New Dynarray module - New `-H` flag for hidden include directories - - Project-wide occurence metadata support for developer tools + - Project-wide occurrence metadata support for developer tools - Raw identifiers - Local open in type expressions - Around 20 new functions in the standard library @@ -30,7 +30,7 @@ Some of the highlights in OCaml 5.2.0 are: - ThreadSanitizer support - New Dynarray module - New `-H` flag for hidden include directories -- Project-wide occurence metadata support for developer tools +- Project-wide occurrence metadata support for developer tools - Raw identifiers - Local open in type expressions @@ -147,7 +147,7 @@ The user manual for OCaml can be: of Emacs info files -## Changes +## Changes (Changes that can break existing programs are marked with a "breaking change" warning) @@ -333,7 +333,7 @@ The user manual for OCaml can be: - [#12814](https://github.com/ocaml/ocaml/issues/12814): More detailed failure messages from `input_value` and `Marshal.from_*` (Xavier Leroy, review by Stephen Dolan and Anil Madhavapeddy) -- [#12815](https://github.com/ocaml/ocaml/issues/12815): Correctly format multiline locations in exception backtraces in the compiler driver's +- [#12815](https://github.com/ocaml/ocaml/issues/12815): Correctly format multiline locations in exception backtraces in the compiler driver's style. (David Allsopp, review by Gabriel Scherer) @@ -521,7 +521,7 @@ gives more robust semantics to newlines in string literals. - [#12825](https://github.com/ocaml/ocaml/issues/12825): Disable common subexpression elimination for atomic loads... again. (Gabriel Scherer, review by KC Sivaramakrishnan, Xavier Leroy and Vincent Laviron, report by Vesa Karvonen) - + ### Other Libraries: - [#12213](https://github.com/ocaml/ocaml/issues/12213): `Dynlink` library, improve legibility of error messages @@ -599,7 +599,7 @@ gives more robust semantics to newlines in string literals. * (*Breaking Change*) [#12942](https://github.com/ocaml/ocaml/issues/12942): Fix line ordering in some module inclusion error messages (Nick Roberts, review by Florian Angeletti, report by Carl Eastlund) - + ### Manual and Documentation: - [#12338](https://github.com/ocaml/ocaml/issues/12338): Clarification of the documentation of process related function in diff --git a/data/releases/5.2.1.md b/data/releases/5.2.1.md index 63b8d7bfdd..c0493e2a5e 100644 --- a/data/releases/5.2.1.md +++ b/data/releases/5.2.1.md @@ -2,7 +2,7 @@ kind: compiler version: 5.2.1 date: 2024-11-18 -is_latest: true +is_latest: false intro: | This page describes OCaml version **5.2.1**, released on Nov 18, 2024. Go [here](/releases) for a list of all releases. diff --git a/data/releases/5.3.0.md b/data/releases/5.3.0.md new file mode 100644 index 0000000000..d498640a70 --- /dev/null +++ b/data/releases/5.3.0.md @@ -0,0 +1,839 @@ +--- +kind: compiler +version: 5.3.0 +date: 2025-01-08 +is_latest: true +intro: | + This page describes OCaml version **5.3.0**, released on + 2025-01-08. Go [here](/releases) for a list of all releases. + + This release is available as an [opam](/p/ocaml/5.3.0) package. +highlights: | + - Syntax for deep effect handlers + - Restored MSVC port + - Re-introduced statistical memory profiling + - More space-efficient implementation of Dynarray + - utf-8 encoded Unicode source files and modest support of Unicode identifiers + - Improved metadata on the pairs of declarations and definitions for merlin. + - Around 20 new functions in the standard library + - Many fixes and improvements in the runtime + - Improved error messages for first-class modules, functors, labeled arguments, + type clashes. + - Numerous bug fixes +--- + +## What's New + +Some of the highlights in OCaml 5.3.0 are: + +- Syntax for deep effect handlers +- Restored MSVC port +- Re-introduced statistical memory profiling +- More space-efficient implementation of Dynarray +- utf-8 encoded Unicode source files and modest support of Unicode identifiers +- Improved metadata on the pairs of declarations and definitions for merlin. + +And a lot of incremental changes: + +- Around 20 new functions in the standard library +- Many fixes and improvements in the runtime +- Improved error messages for first-class modules, functors, labeled arguments, +type clashes. +- Numerous bug fixes + +For a comprehensive list of changes and details on all new features, +bug fixes, optimisations, etc., please consult the +[changelog](#Changes). + +--- + +## Installation Instructions + +The base compiler can be installed as an opam switch with the following commands: +```bash +opam update +opam switch create 5.3.0 +``` + +The source code for OCaml 5.3.0 is also directly available on: + +* [GitHub](https://github.com/ocaml/ocaml/archive/5.3.0.tar.gz) +* [OCaml archives at Inria](https://caml.inria.fr/pub/distrib/ocaml-5.3/ocaml-5.3.0.tar.gz) + + +### Configuration Options + +The configuration of the installed [opam](https://opam.ocaml.org/) switch can be tuned with the +following options: + +- `ocaml-option-afl`: Set OCaml to be compiled with `afl-fuzz` instrumentation +- `ocaml-option-bytecode-only`: Compile OCaml without the native-code compiler +- `ocaml-option-flambda`: Set OCaml to be compiled with `flambda` activated +- `ocaml-option-musl`: Set OCaml to be compiled with `musl-gcc` +- `ocaml-option-no-flat-float-array`: Set OCaml to be compiled with `--disable-flat-float-array` +- `ocaml-option-static`: Set OCaml to be compiled with `musl-gcc -static` +- `ocaml-option-tsan` : Set OCaml to be compiled with thread sanitiser support +- `ocaml-option-address-sanitizer`: Set OCaml to be compiled with address sanitiser +- `ocaml-option-leak-sanitizer`: Set OCaml to be compiled with leak sanitiser +- `ocaml-option-fp`: Set OCaml to be compiled with frame pointers + +For instance, one can install a switch with both `flambda` and the `--disable-flat-float-array` option with + + +``` +opam switch create 5.3.0+flambda+nffa ocaml-variants.5.3.0+options ocaml-option-flambda ocaml-option-no-flat-float-array +``` + + +Source Distribution +------------------- + +- [Source + tarball](https://github.com/ocaml/ocaml/archive/5.3.0.tar.gz) + (`.tar.gz`) for compilation under Unix (including Linux and macOS X) + and Microsoft Windows (including Cygwin) +- Also available in + [`.zip`](https://github.com/ocaml/ocaml/archive/5.3.0.zip) + format +- [Opam](https://opam.ocaml.org/) is a source-based distribution of + OCaml and many companion libraries and tools. Compilation and + installation are automated by powerful package managers. +- The official development repo is hosted on + [GitHub](https://github.com/ocaml/ocaml). + +The +[INSTALL](https://ocaml.org/releases/5.3/notes/INSTALL.adoc) file +of the distribution provides detailed compilation and installation +instructions. See also the [Windows release +notes](https://ocaml.org/releases/5.3/notes/README.win32.adoc) for +instructions on how to build under Windows. + +Alternative Compilers +--------------------- + +Additionally, the following projects allow you to compile OCaml code to +targets traditionally associated with other languages: + +* [Js_of_ocaml](http://ocsigen.org/js_of_ocaml/) is a stable OCaml + to JavaScript compiler. + +User Manual +------------- + +The user manual for OCaml can be: + +- [Browsed online](https://ocaml.org/releases/5.3/manual/index.html) +- Downloaded as a single + [PDF](https://ocaml.org/releases/5.3/ocaml-5.3-refman.pdf) + or [plain + text](https://ocaml.org/releases/5.3/ocaml-5.3-refman.txt) + document +- Downloaded as a single + [TAR](https://ocaml.org/releases/5.3/ocaml-5.3-refman-html.tar.gz) + or + [ZIP](https://ocaml.org/releases/5.3/ocaml-5.3-refman-html.zip) + archive of HTML files +- Downloaded as a single + [tarball](https://ocaml.org/releases/5.3/ocaml-5.3-refman.info.tar.gz) + of Emacs info files + + +## Changes + +(Changes that can break existing programs are marked with a "*") + +### Restored backend: + +- [#12954](https://github.com/ocaml/ocaml/issues/12954): Restore the MSVC port + (David Allsopp, Antonin Décimo, Samuel Hym, and Miod Vallat, review by Nicolás + Ojeda Bär) + +- [#13093](https://github.com/ocaml/ocaml/issues/13093): Allow building the MSVC port with clang-cl. + (Antonin Décimo, review by Nicolás Ojeda Bär, Samuel Hym, + David Allsopp and Sébastien Hinderer) + +### Language features: + +- [#12309](https://github.com/ocaml/ocaml/issues/12309), [#13158](https://github.com/ocaml/ocaml/issues/13158): Add syntax support for deep effect handlers + (Leo White, Tom Kelly, Anil Madhavapeddy, KC Sivaramakrishnan, Xavier Leroy + and Florian Angeletti, review by the same, Hugo Heuzard, and Ulysse Gérard) + +- [#11736](https://github.com/ocaml/ocaml/issues/11736), [#12664](https://github.com/ocaml/ocaml/issues/12664), [#13628](https://github.com/ocaml/ocaml/issues/13628): Support utf-8 encoded source files and latin-9 + compatible identifiers. + (Xavier Leroy and Florian Angeletti, review by Daniel Bünzli and + Jules Aguillon) + + +- [#12828](https://github.com/ocaml/ocaml/issues/12828), [#13283](https://github.com/ocaml/ocaml/issues/13283): Add short syntax for dependent functor types `(X:A) -> ...` + (Jeremy Yallop, review by Nicolás Ojeda Bär and Gabriel Scherer) + +### Type system + +- [#11891](https://github.com/ocaml/ocaml/issues/11891), [#12507](https://github.com/ocaml/ocaml/issues/12507): Allow to name new locally abstract types in constructor type + annotations. + (Jacques Garrigue, report and review by Gabriel Scherer and Florian Angeletti) + +### Runtime system: + +- [#11911](https://github.com/ocaml/ocaml/issues/11911), [#12923](https://github.com/ocaml/ocaml/issues/12923): Multicore statistical memory profiling. + This restores a notable OCaml 4 feature that was missing + in OCaml 5. + (Nick Barnes, review by Stephen Dolan, Jacques-Henri Jourdan + and Guillaume Munch-Maccagnoni). + + +- [#13419](https://github.com/ocaml/ocaml/issues/13419): Fix memory bugs in runtime events system. + (B. Szilvasy and Nick Barnes, review by Miod Vallat, Nick Barnes, + Tim McGilchrist, and Gabriel Scherer) + +- [#13364](https://github.com/ocaml/ocaml/issues/13364): Emit major slice counters in the runtime events. + (KC Sivaramakrishnan and Sadiq Jaffer, review by Gabriel Scherer) + +- [#13382](https://github.com/ocaml/ocaml/issues/13382): Add more documentation for Runtime_events types + (Sadiq Jaffer, review by Tim McGilchrist, Miod Vallat and KC Sivaramakrishnan) + +- [#13370](https://github.com/ocaml/ocaml/issues/13370): Fix a low-probability crash when calling Gc.counters. + (Demi Marie Obenour, review by Gabriel Scherer) + +- [#13272](https://github.com/ocaml/ocaml/issues/13272): Allow maximum number of domains to be specified as a OCAMLRUNPARAM + parameter. + (KC Sivaramakrishnan, review by Guillaume Munch-Maccagnoni, Miod Vallat, + Gabriel Scherer, David Allsopp, request by Zachary Yedidia). + +- [#12579](https://github.com/ocaml/ocaml/issues/12579): OS-based Synchronisation for Stop-the-World Sections + (B. Szilvasy, review by Miod Vallat, Nick Barnes, Olivier Nicole, + Gabriel Scherer and Damien Doligez) + +- [#12789](https://github.com/ocaml/ocaml/issues/12789): Restore caml_unregister_frametable from OCaml 4 + (Frédéric Recoules, review by Gabriel Scherer) + +- [#13003](https://github.com/ocaml/ocaml/issues/13003): new, more consistent names for array-creation C functions + (Gabriel Scherer, review by Olivier Nicole) + +- [#13013](https://github.com/ocaml/ocaml/issues/13013): introduce a `caml_result` type to supersede the + use of 'encoded exception values' in the FFI. + (Gabriel Scherer, review by Damien Doligez, + Guillaume Munch-Maccagnoni and Xavier Leroy, + suggested by Guillaume Munch-Maccagnoni) + +- [#12407](https://github.com/ocaml/ocaml/issues/12407), [#13226](https://github.com/ocaml/ocaml/issues/13226): Resource-handling improvements: add + exception-returning variants for all exception-raising functions in + `caml/fail.h`, for the purpose of cleaning-up state and resources + before raising. + (Guillaume Munch-Maccagnoni, review by Damien Doligez, Xavier Leroy + and Gabriel Scherer) + +- [#13086](https://github.com/ocaml/ocaml/issues/13086): Avoid spurious major GC slices. + (Damien Doligez, report by Stephen Dolan, review by Gabriel Scherer + and Stephen Dolan) + +- [#11779](https://github.com/ocaml/ocaml/issues/11779), [#13117](https://github.com/ocaml/ocaml/issues/13117): Improve logic for fiber stack alignment. + (Miod Vallat, report by Damien Doligez, review by Gabriel Scherer) + +- [#12839](https://github.com/ocaml/ocaml/issues/12839): Remove ATOMIC_UINTNAT_INIT from camlatomic.h (as part of a larger + cleanup of camlatomic.h) + (David Allsopp, review by Antonin Décimo, Sébastien Hinderer, Samuel Hym, + Guillaume Munch-Maccagnoni and Miod Vallat) + +- [#13163](https://github.com/ocaml/ocaml/issues/13163): Enable frame pointers on macOS x86_64 + (Tim McGilchrist, review by Sébastien Hinderer and Fabrice Buoro) + +- [#12951](https://github.com/ocaml/ocaml/issues/12951): Constify constructors and flags tables in C code (take 2). + Now these tables will go in the readonly segment, where they belong. + (Antonin Décimo, review by David Allsopp) + +- [#10696](https://github.com/ocaml/ocaml/issues/10696): Introduce __has_attribute and __has_c_attributes in + to test the support of specific attributes in C + code. Introduce fallthrough as a wrapper around the fallthrough + attribute. + (Antonin Décimo, review by Nicolás Ojeda Bär, Xavier Leroy, and + Gabriel Scherer) + +- [#13083](https://github.com/ocaml/ocaml/issues/13083): Use macros from limits.h to avoid signed-integer wrap-around. + Introduce CAML_{U,}INTNAT_{MIN,MAX} macros to expose {u,}intnat limits. + (Antonin Décimo, review by Nick Barnes, Xavier Leroy, Gabriel Scherer, + and Miod Vallat) + +- [#13239](https://github.com/ocaml/ocaml/issues/13239): Check whether the compiler supports the labels as values + extension to enable threaded code interpretation. + (Antonin Décimo, review by Miod Vallat) + +- [#13238](https://github.com/ocaml/ocaml/issues/13238): Enable software prefetching on x86 and x86_64 when building + with MSVC or clang-cl. + (Antonin Décimo, review by Miod Vallat) + +- [#13241](https://github.com/ocaml/ocaml/issues/13241), [#13261](https://github.com/ocaml/ocaml/issues/13261), [#13271](https://github.com/ocaml/ocaml/issues/13271): Add CFI_SIGNAL_FRAME to ARM64 and RiscV runtimes, + for the purpose of displaying backtraces correctly in GDB. + (Tim McGilchrist, review by Miod Vallat, Gabriel Scherer and + KC Sivaramakrishnan) + +- [#13139](https://github.com/ocaml/ocaml/issues/13139): Simplify CAMLalign to always use C23/C++11 alignas or C11 + _Alignas. Ensures that stat data is always aligned to the best + boundary. + (Antonin Décimo, review by Miod Vallat and Xavier Leroy) + +- [#13280](https://github.com/ocaml/ocaml/issues/13280): Check for support of compiler attributes. Allows using + compiler attributes with clang-cl. + (Antonin Décimo, review by Miod Vallat) + +- [#13243](https://github.com/ocaml/ocaml/issues/13243): Enable C compiler warnings internally when building with + clang-cl or MSVC. Provide fixes too. + (Antonin Décimo, review by Miod Vallat and Xavier Leroy) + +- [#13242](https://github.com/ocaml/ocaml/issues/13242): Define and use unreachable and trap annotation, and clean-up some + runtime assertions. + (Antonin Décimo, review by Miod Vallat, Gabriel Scherer, and David Allsopp) + +- [#13402](https://github.com/ocaml/ocaml/issues/13402), [#13512](https://github.com/ocaml/ocaml/issues/13512), [#13549](https://github.com/ocaml/ocaml/issues/13549), [#13553](https://github.com/ocaml/ocaml/issues/13553): Revise bytecode implementation of callbacks + so that it no longer produces dangling registered bytecode fragments. + (Xavier Leroy, report by Jan Midtgaard, analysis by Stephen Dolan, + review by Miod Vallat) + +- [#13407](https://github.com/ocaml/ocaml/issues/13407): Add Runtime_events.EV_EMPTY_MINOR + (Thomas Leonard) + +- [#13522](https://github.com/ocaml/ocaml/issues/13522): Confirm runtime events ring is still active after callback. + (KC Sivaramakrishnan, review by Sadiq Jaffer and Miod Vallat) + +- [#13529](https://github.com/ocaml/ocaml/issues/13529): Do not write to event ring after going out of stw participant set. + (KC Sivaramakrishnan, review by Sadiq Jaffer) + +### Code generation and optimizations: + +- [#13014](https://github.com/ocaml/ocaml/issues/13014): Enable compile-time option -function-sections on all previously + unsupported native backends (POWER, riscv64 and s390x) + (Miod Vallat, review by Nicolás Ojeda Bär) + +- [#7241](https://github.com/ocaml/ocaml/issues/7241), [#12555](https://github.com/ocaml/ocaml/issues/12555), [#13076](https://github.com/ocaml/ocaml/issues/13076), [#13138](https://github.com/ocaml/ocaml/issues/13138), [#13338](https://github.com/ocaml/ocaml/issues/13338), [#13152](https://github.com/ocaml/ocaml/issues/13152), [#13153](https://github.com/ocaml/ocaml/issues/13153), [#13154](https://github.com/ocaml/ocaml/issues/13154): + fix a soundness bug in the pattern-matching compiler + when side-effects mutate the scrutinee during matching. + (Gabriel Scherer, review by Nick Roberts) + +- [#13341](https://github.com/ocaml/ocaml/issues/13341): a warning when the pattern-matching compiler pessimizes code + because side-effects may mutate the scrutinee during + matching. (This warning is disabled by default, as this rarely + happens and its performance impact is typically not noticeable.) + (Gabriel Scherer, review by Nick Roberts, Florian Angeletti + and David Allsopp) + +- [#13179](https://github.com/ocaml/ocaml/issues/13179): Fix evaluation of toplevel lets in classes containing + local opens + (Vincent Laviron, review by Hugo Heuzard, Nathanaëlle Courant + and Gabriel Scherer) + +- [#13543](https://github.com/ocaml/ocaml/issues/13543): Remove some String-Bytes conversion from the stdlib to behave better + with js_of_ocaml + (Hugo Heuzard, review by Gabriel Scherer) + +### Standard library: + +- [#12885](https://github.com/ocaml/ocaml/issues/12885): move Dynarray to an unboxed representation + (Gabriel Scherer, suggestions by Vincent Laviron, + review by Olivier Nicole and Simon Cruanes, Yann Leray, Alain Frisch) + + +- [#12884](https://github.com/ocaml/ocaml/issues/12884): Add `Queue.drop` + (Léo Andrès, review by Nicolás Ojeda Bär and Gabriel Scherer) + +- [#13168](https://github.com/ocaml/ocaml/issues/13168): In Array.shuffle, clarify the code that validates the + result of the user-supplied function `rand`, and improve the + error message that is produced when this result is invalid. + (François Pottier, review by Florian Angeletti, Daniel Bünzli + and Gabriel Scherer) + +- [#12133](https://github.com/ocaml/ocaml/issues/12133): Expose support for printing substrings in Format + (Florian Angeletti, review by Daniel Bünzli, Gabriel Scherer + and Nicolás Ojeda Bär) + +- [#12869](https://github.com/ocaml/ocaml/issues/12869): Add List.take, List.drop, List.take_while and List.drop_while + (Kate Deplaix and Oscar Butler-Aldridge, review by Nicolás Ojeda Bär, + Craig Ferguson and Gabriel Scherer) + +- [#13047](https://github.com/ocaml/ocaml/issues/13047): Add Sys.poll_actions to (only) run pending runtime actions. + (Nick Barnes, review by Gabriel Scherer, Guillaume Munch-Maccagnoni, and + Vincent Laviron) + +- [#13144](https://github.com/ocaml/ocaml/issues/13144): Dynarray.{equal, compare} + (Gabriel Scherer, + review by Jeremy Yallop, Daniel Bünzli and Olivier Nicole, + request by Olivier Nicole) + +- [#13171](https://github.com/ocaml/ocaml/issues/13171): expose `Domain.self_index : unit -> int` (a somewhat-dense + indexing of currently-running domains) for advanced use-cases of + domain-indexed concurrent data structures. + (Gabriel Scherer, + review by KC Sivaramakrishnan, Miod Vallat and Nicolás Ojeda Bär, + report by Vesa Karvonen) + +- [#13197](https://github.com/ocaml/ocaml/issues/13197): Dynarray.blit, which allows to extend the destination + dynarray (0 <= dst_pos <= dst_length). + (Gabriel Scherer, report by Hazem Elmasry, + review by Olivier Nicole, Hazem Elmasry and Nicolás Ojeda Bär) + +* (*breaking change*) [#13240](https://github.com/ocaml/ocaml/issues/13240): Add Uchar.seeded_hash, Change Uchar.hash implementation. + Previously, Uchar.hash was aliased to Uchar.to_int. If you need that behavior, + change your module instantiation from eg `module HT = Hashtbl.Make(Uchar)` to + ``` + module HT = Hashtbl.Make(struct + ... + let hash = Uchar.to_int + end) + ``` + If the current implementation is desired, and you have a hashtable module `HT` + (produced with the `Make` functor) in persistent storage, use `HT.rebuild` to + ensure it doesn't break when reading from or writing to buckets. + (Hazem ElMasry, review by Gabriel Scherer and Nicolás Ojeda Bär) + +- [#13318](https://github.com/ocaml/ocaml/issues/13318): Fix regression in GC alarms, and fix them for flambda. + (Guillaume Munch-Maccagnoni, report by Benjamin Monate, review by + Vincent Laviron and Gabriel Scherer) + +- [#13296](https://github.com/ocaml/ocaml/issues/13296): Add mem, memq, find_opt, find_index, find_map and find_mapi + to Dynarray. + (Jake H, review by Gabriel Scherer and Florian Angeletti) + +### Other libraries: + +- [#11996](https://github.com/ocaml/ocaml/issues/11996): release the dependency of dynlink on compilerlibs. + (Sébastien Hinderer and Stephen Dolan, review by Damien Doligez and + Hugo Heuzard) + +- [#13326](https://github.com/ocaml/ocaml/issues/13326): Implement Unix.O_APPEND on windows. + (Romain Beauxis, review by Miod Vallat, Gabriel Scherer and Antonin Décimo) + +### Tools: + +- [#11716](https://github.com/ocaml/ocaml/issues/11716): ocamllex: mismatched parentheses and curly brackets are now caught + by ocamllex, instead of causing invalid OCaml code to be generated. + (Demi Marie Obenour, review by Damien Doligez and Xavier Leroy) + +- [#12904](https://github.com/ocaml/ocaml/issues/12904): Run the testsuite with ThreadSanitizer on a PR when label + `run-thread-sanitizer` is added + (Olivier Nicole, suggested by Sébastien Hinderer and David Allsopp, review by + Gabriel Scherer) + +* (*breaking change*) [#13114](https://github.com/ocaml/ocaml/issues/13114): Support ocamldebug remote debugging over IPv6 on all + platforms, and over Unix domain sockets on Windows. + (Antonin Décimo, review by Gabriel Scherer and Miod Vallat) + +- [#13136](https://github.com/ocaml/ocaml/issues/13136): Rewrite GDB extensions and macros in debugger-agnostic Python, and add + LLDB support for them. + (Nick Barnes, review by Tim McGilchrist and Gabriel Scherer) + +### Toplevel: + +- [#12891](https://github.com/ocaml/ocaml/issues/12891): Improved styling for initial prompt + (Florian Angeletti, review by Gabriel Scherer) + +- [#13053](https://github.com/ocaml/ocaml/issues/13053): Improved display of builtin types such as `_ list` when aliased. + (Samuel Vivien, review by Florian Angeletti) + +### Manual and documentation: + +- [#13370](https://github.com/ocaml/ocaml/issues/13370): Document that that temporary variables holding GCd pointers must + not be live across a GC. + (Demi Marie Obenour) + +- [#12298](https://github.com/ocaml/ocaml/issues/12298): Manual: emphasize that Bigarray.int refers to an OCaml integer, + which does not match the C int type. + (Edwin Török, review by Florian Angeletti) + +- [#12868](https://github.com/ocaml/ocaml/issues/12868): Manual: simplify style colours of the post-processed manual and API + HTML pages, and fix the search button icon + (Yawar Amin, review by Simon Grondin, Gabriel Scherer, and Florian Angeletti) + +- [#12949](https://github.com/ocaml/ocaml/issues/12949): document OCaml release cycles and version strings in + `release-info/introduction.md`. + (Florian Angeletti, review by Fabrice Buoro, Kate Deplaix, Damien Doligez, and + Gabriel Scherer) + +- [#12976](https://github.com/ocaml/ocaml/issues/12976): Manual: use webman//*.html and + webman//api/ for OCaml.org HTML manual generation + (Shakthi Kannan, review by Hannes Mehnert, and Florian Angeletti) + +- [#13045](https://github.com/ocaml/ocaml/issues/13045): Emphasize caution about behaviour of custom block finalizers. + (Nick Barnes) + +- [#13216](https://github.com/ocaml/ocaml/issues/13216): document the new `caml_result` type in the FFI chapter of the manual. + (Gabriel Scherer, review by Miod Vallat, Daniel Bünzli, Nick Barnes, + Guillaume Munch-Maccagnoni and Antonin Décimo) + +- [#13287](https://github.com/ocaml/ocaml/issues/13287): stdlib/sys.mli: Update documentation on Sys.opaque_identity + following [#9412](https://github.com/ocaml/ocaml/issues/9412). + (Matt Walker, review by Guillaume Munch-Maccagnoni and Vincent Laviron) + +- [#13295](https://github.com/ocaml/ocaml/issues/13295): Use syntax for deep effect handlers in the effect handlers manual + page. + (KC Sivaramakrishnan, review by Anil Madhavapeddy, Florian Angeletti and Miod + Vallat) + +- [#13424](https://github.com/ocaml/ocaml/issues/13424): Fix `Gc.quick_stat` documentation to clarify that returned fields + `live_words`, `live_blocks`, `free_words`, and `fragments` are not zero. + (Jan Midtgaard, review by Damien Doligez and KC Sivaramakrishnan) + +- [#13440](https://github.com/ocaml/ocaml/issues/13440): Update documentation of `Gc.{control,get,set}` to reflect fields + not currently supported on OCaml 5. + (Jan Midtgaard, review by Gabriel Scherer) + +- [#13469](https://github.com/ocaml/ocaml/issues/13469), [#13474](https://github.com/ocaml/ocaml/issues/13474), [#13535](https://github.com/ocaml/ocaml/issues/13535): Document that [Hashtbl.create n] creates a hash table + with a default minimal size, even if [n] is very small or negative. + (Antonin Décimo, Nick Bares, report by Nikolaus Huber and Jan Midtgaard, + review by Florian Angeletti, Anil Madhavapeddy, Gabriel Scherer, + and Miod Vallat) + +- [#13666](https://github.com/ocaml/ocaml/issues/13666): Rewrite parts of the example code around nested lists in Chapter 6 + (Polymorphism and its limitations -> Polymorphic recursion) giving the + "depth" function [in the non-polymorphically-recursive part of the example] + a much more sensible behavior; also fix a typo and some formatting. + (Frank Steffahn, review by Florian Angeletti) + +- [#13668](https://github.com/ocaml/ocaml/issues/13668): Document the basic support for unicode identifiers and the switch to + UTF-8 encoded Unicode text for OCaml source file + (Florian Angeletti, review by Nicolás Ojeda Bär and Daniel Bünzli) + +### Compiler user-interface and warnings: + +* (*breaking change*) [#12084](https://github.com/ocaml/ocaml/issues/12084), [#13669](https://github.com/ocaml/ocaml/issues/13669), [#13673](https://github.com/ocaml/ocaml/issues/13673): Check link order when creating archive and when using + ocamlopt. + (Hugo Heuzard, review by Stefan Muenzel and Sébastien Hinderer) + +- [#12980](https://github.com/ocaml/ocaml/issues/12980): Explain type mismatch involving first-class modules by including + the module level error message + (Florian Angeletti, review by Vincent Laviron) + +- [#12985](https://github.com/ocaml/ocaml/issues/12985), [#12988](https://github.com/ocaml/ocaml/issues/12988): Better error messages for partially applied functors. + (Florian Angeletti, report by Arthur Wendling, review by Gabriel Scherer) + +- [#13034](https://github.com/ocaml/ocaml/issues/13034), [#13260](https://github.com/ocaml/ocaml/issues/13260): Better error messages for mismatched function labels + (Florian Angeletti, report by Daniel Bünzli, review by Gabriel Scherer and + Samuel Vivien) + +- [#13051](https://github.com/ocaml/ocaml/issues/13051): Add a "Syntax error" to error messages for invalid package signatures. + (Samuel Vivien, review by Gabriel Scherer) + +- [#13099](https://github.com/ocaml/ocaml/issues/13099): Fix erroneous loading of cmis for some module type errors. + (Nick Roberts, review by Florian Angeletti) + +- [#13151](https://github.com/ocaml/ocaml/issues/13151), name conflicts explanation as a footnote + (Florian Angeletti, review by Gabriel Scherer) + +- [#13228](https://github.com/ocaml/ocaml/issues/13228): Re-export Cmt2annot.{iterator,binary_part} which had become hidden + since [#11288](https://github.com/ocaml/ocaml/issues/11288) and broke ocamlbrowser. + (David Allsopp, report by Jacques Garrigue, review by Sébastien Hinderer) + +- [#13251](https://github.com/ocaml/ocaml/issues/13251): Register printer for errors in Emitaux + (Vincent Laviron, review by Miod Vallat and Florian Angeletti) + +- [#13255](https://github.com/ocaml/ocaml/issues/13255): Re-enable warning 34 for unused locally abstract types + (Nick Roberts, review by Chris Casinghino and Florian Angeletti) + +- [#12182](https://github.com/ocaml/ocaml/issues/12182): Improve the type clash error message. + For example, this message: + This expression has type ... + is changed into: + The constant "42" has type ... + (Jules Aguillon, review by Gabriel Scherer and Florian Angeletti) + +- [#13471](https://github.com/ocaml/ocaml/issues/13471): add `-keywords ` flag to define the list of keywords + recognized by the lexer, for instance `-keywords 5.2` disable the `effect` + keyword. + (Florian Angeletti, review by Gabriel Scherer) + +### Internal/compiler-libs changes: + +- [#13286](https://github.com/ocaml/ocaml/issues/13286): Distinguish unique identifiers `Shape.Uid.t` according to their + provenance: either an implementation or an interface. + (Ulysse Gérard, review by Florian Angeletti and Leo White) + +- [#13308](https://github.com/ocaml/ocaml/issues/13308): keep track of relations between declaration in the cmt files. This is + useful information for external tools for navigation and analysis purposis. + (Ulysse Gérard, Florian Angeletti, review by Florian Angeletti and Gabriel + Scherer) + + +- [#11129](https://github.com/ocaml/ocaml/issues/11129), [#11148](https://github.com/ocaml/ocaml/issues/11148): enforce that ppxs do not produce `parsetree`s with + an empty list of universally quantified type variables + (`. int -> int` instead of `'a . int -> int'`) + (Florian Angeletti, report by Simmo Saan, review by Gabriel Scherer) + +- [#12534](https://github.com/ocaml/ocaml/issues/12534): document and refactor Matching.mk_failaction_pos + (Gabriel Scherer, review by Vincent Laviron and Nick Roberts) + +- [#13076](https://github.com/ocaml/ocaml/issues/13076): change the handling of Match_failure exits in the pattern-matching + compiler, to prepare for a complete fix for [#7241](https://github.com/ocaml/ocaml/issues/7241) + (Gabriel Scherer, review by Thomas Refis and Nick Roberts) + +- [#12896](https://github.com/ocaml/ocaml/issues/12896): Simplify the compilation of custom bytecode runtimes by explicitly + compiling the primitives file before calling the linker. Tidy-up both the + generating code and the output itself for C code being generated by the + bytecode linker in `-custom` and `-output-*` modes. + (David Allsopp, Antonin Décimo and Samuel Hym, review by Vincent Laviron) + +- [#12932](https://github.com/ocaml/ocaml/issues/12932): Remove useless code in Typecore.type_label_exp (was a fix for [#4862](https://github.com/ocaml/ocaml/issues/4862)) + (Jacques Garrigue, review by Gabriel Scherer) + +- [#12943](https://github.com/ocaml/ocaml/issues/12943): Make transient_expr.scope a bitfield, and use it to store marks. + Marks are automatically allocated, and removed when leaving their scope. + Falls back to using TransientTypeSet when marks are exhausted. + (Jacques Garrigue and Takafumi Saikawa, review by Basile Clément) + +- [#12946](https://github.com/ocaml/ocaml/issues/12946): Make generalization automatic when leaving scope. + As a result, the `Ctype.generalize*` and `Ctype.correct_levels` functions + were removed. The latter is now called `Ctype.duplicate_type`. + (Jacques Garrigue and Takafumi Saikawa, review by Richard Eisenberg) + +- [#12968](https://github.com/ocaml/ocaml/issues/12968): Attach location to constants in the parsetree + (Jules Aguillon, review by Gabriel Scherer) + +- [#12959](https://github.com/ocaml/ocaml/issues/12959), [#13055](https://github.com/ocaml/ocaml/issues/13055): Avoid an internal error on recursive module type inconsistency + (Florian Angeletti, review by Jacques Garrigue and Gabriel Scherer) + +- [#13049](https://github.com/ocaml/ocaml/issues/13049): graphical debugging printer for types + (Florian Angeletti, review by Gabriel Scherer) + +- [#13074](https://github.com/ocaml/ocaml/issues/13074), [#13082](https://github.com/ocaml/ocaml/issues/13082), [#13084](https://github.com/ocaml/ocaml/issues/13084): refactoring in the pattern-matching compiler + (Gabriel Scherer, review by Thomas Refis, Vincent Laviron and Nick Roberts) + +- [#13067](https://github.com/ocaml/ocaml/issues/13067): rework volatile memory access rules under TSan to consider properly + aligned smaller-than-register read operations as atomic, which gets rid of + false positives on s390x + (Miod Vallat, review by Fabien Buoro) + +- [#13162](https://github.com/ocaml/ocaml/issues/13162): Use quoted strings to clarify code being generated. + (Antonin Décimo, review by Miod Vallat and Gabriel Scherer) + +- [#13015](https://github.com/ocaml/ocaml/issues/13015): Emit floating-point literals in .rodata section on ELF arm64 + platforms (Linux, *BSD). + (Miod Vallat, review by Nicolás Ojeda Bär) + +- [#13169](https://github.com/ocaml/ocaml/issues/13169), [#13311](https://github.com/ocaml/ocaml/issues/13311): Introduce a document data type for compiler messages + rather than relying on `Format.formatter -> unit` closures. + (Florian Angeletti, review by Gabriel Scherer) + +- [#13193](https://github.com/ocaml/ocaml/issues/13193): Remove the unused env_init field from class blocks + (Vincent Laviron, review by Jacques Garrigue) + +- [#13257](https://github.com/ocaml/ocaml/issues/13257): integrate MetaOCaml in the Menhir grammar to ease MetaOCaml + maintenance. This is a purely internal change: there is no support + in the lexer, so no change to the surface OCaml grammar. + (Oleg Kiselyov, Gabriel Scherer and Florian Angeletti, + review by Jeremy Yallop) + +- [#13289](https://github.com/ocaml/ocaml/issues/13289): Use C99 for loop to reduce the scope of the for loop iterator. + (Antonin Décimo, review by Miod Vallat and Gabriel Scherer) + +- [#13336](https://github.com/ocaml/ocaml/issues/13336): compiler-libs, split the `Printtyp` in three to only keep + "user-friendly" functions in the `Printtyp` module. + (Florian Angeletti, review by Gabriel Scherer) + +- [#13361](https://github.com/ocaml/ocaml/issues/13361): split runtime/array.c functions to consistently expose + uniform_array and floatarray versions, use floatarray versions + in Float.Array. + (Gabriel Scherer, review by Nicolás Ojeda Bär) + +- [#13507](https://github.com/ocaml/ocaml/issues/13507): A small refactoring to [free_vars] to make it a bit faster + by not allocating a list when the list is not necessary. + (Richard Eisenberg, review by Jacques Garrigue) + +### Build system: + +- [#12909](https://github.com/ocaml/ocaml/issues/12909): Reorganise how MKEXE_VIA_CC is built to make it correct for MSVC by + grouping all the linker flags at the end of the C compiler commandline + (David Allsopp and Samuel Hym, review by Nicolás Ojeda Bär) + +- [#12992](https://github.com/ocaml/ocaml/issues/12992), [#13009](https://github.com/ocaml/ocaml/issues/13009): Check that flexlink can be executed only when building in a + native windows environment. + (Romain Beauxis, review by David Allsopp and Sébastien Hinderer) + +- [#12996](https://github.com/ocaml/ocaml/issues/12996): Only link with -lgcc_eh when available. + (Romain Beauxis, review by David Allsopp and Miod Vallat) + +* (*breaking change*) [#13200](https://github.com/ocaml/ocaml/issues/13200): Do not use CFLAGS for linking. + (Sébastien Hinderer, review by Gabriel Scherer, Antonin Décimo, + Miod Vallat and Samuel Hym) + +- [#13201](https://github.com/ocaml/ocaml/issues/13201), [#13244](https://github.com/ocaml/ocaml/issues/13244): Fix and speedup builds with TSan. + (Sébastien Hinderer, review by Miod Vallat, Gabriel Scherer and + Olivier Nicole) + +* (*breaking change*) [#12578](https://github.com/ocaml/ocaml/issues/12578), [#12589](https://github.com/ocaml/ocaml/issues/12589), [#13322](https://github.com/ocaml/ocaml/issues/13322), [#13519](https://github.com/ocaml/ocaml/issues/13519): Use configured CFLAGS and CPPFLAGS *only* + during the build of the compiler itself. Do not use them when + compiling third-party C sources through the compiler. Flags for + compiling third-party C sources can still be specified at configure + time in the COMPILER_{BYTECODE,NATIVE}_{CFLAGS,CPPFLAGS} + configuration variables. + (Sébastien Hinderer, report by William Hu, review by David Allsopp) + +- [#13285](https://github.com/ocaml/ocaml/issues/13285): continue the merge of the sub-makefiles into the root + Makefile started with [#11243](https://github.com/ocaml/ocaml/issues/11243), [#11248](https://github.com/ocaml/ocaml/issues/11248), [#11268](https://github.com/ocaml/ocaml/issues/11268), [#11420](https://github.com/ocaml/ocaml/issues/11420), [#11675](https://github.com/ocaml/ocaml/issues/11675), + [#12198](https://github.com/ocaml/ocaml/issues/12198), [#12321](https://github.com/ocaml/ocaml/issues/12321), [#12586](https://github.com/ocaml/ocaml/issues/12586), [#12616](https://github.com/ocaml/ocaml/issues/12616), [#12706](https://github.com/ocaml/ocaml/issues/12706) and [#13048](https://github.com/ocaml/ocaml/issues/13048). + (Sébastien Hinderer, review by David Allsopp and Florian Angeletti) + +### Bug fixes: + +- [#12854](https://github.com/ocaml/ocaml/issues/12854): Add a test in the regression suite that flags the bug [#12825](https://github.com/ocaml/ocaml/issues/12825). + (Luc Maranget) + +- [#12888](https://github.com/ocaml/ocaml/issues/12888): fix printing of uncaught exceptions in `.cmo` files passed on the + command-line of the toplevel. + (Nicolás Ojeda Bär, review by Florian Angeletti, report by Daniel Bünzli) + +- [#12910](https://github.com/ocaml/ocaml/issues/12910), [#12920](https://github.com/ocaml/ocaml/issues/12920): Fix an unsound interaction between first-class modules + and polymorphic records by saving and restoring univar_pairs. + (Stephen Dolan, review by Gabriel Scherer, report by Jeremy Yallop) + +- [#12994](https://github.com/ocaml/ocaml/issues/12994): Remove un-used and unsafe caml_drop_continuation + (Tim McGilchrist, reviewed by Gabriel Scherer and Miod Vallat) + +- [#12963](https://github.com/ocaml/ocaml/issues/12963): Restore caml_runtime_parameters implementation. This primitive allows + programs to query the runtime parameters supplied to an OCaml program. + Implementation missing since OCaml 5.0. + (Tim McGilchrist, reviewed by David Allsopp and Miod Vallat) + +- [#13012](https://github.com/ocaml/ocaml/issues/13012): parsing: Fix dropped attributes after a '-' or '+' + The syntax '-(1 [@foo])' was incorrectly parsed as '-1'. + (Jules Aguillon, reviewed by Gabriel Scherer, report by Gabriel Scherer) + +* (*breaking change*) [#13070](https://github.com/ocaml/ocaml/issues/13070): On Windows, when configured with bootstrapped flexdll, don't add + +flexdll to the search path when -nostdlib is specified (which then means + -L no longer gets passed to the system linker). + (David Allsopp, review by Florian Angeletti) + +- [#13089](https://github.com/ocaml/ocaml/issues/13089): Fix bug in `runtime_events` library which could result in garbled + output under Windows. + (B. Szilvasy, review by Nicolás Ojeda Bär and Miod Vallat) + +- [#13088](https://github.com/ocaml/ocaml/issues/13088): A few type-checker behaviors look at a type to see if there are + any labeled arguments in it. This sometimes required expansion, which + could, in obscure scenarios, result in superfluous type errors. + (Richard Eisenberg, review by Gabriel Scherer and Jacques Garrigue) + +- [#13103](https://github.com/ocaml/ocaml/issues/13103): FreeBSD/amd64: properly annotate .o files with non-executable stack + notes (Konstantin Belousov, review by Nicolás Ojeda Bär) + +- [#13150](https://github.com/ocaml/ocaml/issues/13150): improve a transitive-closure computation algorithm in the flambda + middle-end to avoid a compilation time blowup on Menhir-generated code + (Florian Weimer, review by Gabriel Scherer and Pierre Chambart, + report by Richard Jones) + +- [#13166](https://github.com/ocaml/ocaml/issues/13166): Fix a MinGW/MSVC Sys.rename regression on renaming a parent directory + to an empty child directory. + (Jan Midtgaard, review by Antonin Décimo, Sébastien Hinderer, and + David Allsopp) + +- [#13185](https://github.com/ocaml/ocaml/issues/13185), [#13192](https://github.com/ocaml/ocaml/issues/13192): Reject type-level module aliases on functor parameter + inside signatures. + (Jacques Garrigue, report by Richard Eisenberg, review by Florian Angeletti) + +- [#13170](https://github.com/ocaml/ocaml/issues/13170): Fix a bug that would result in some floating alerts `[@@@alert ...]` + incorrectly triggering Warning 53. + (Nicolás Ojeda Bär, review by Chris Casinghino and Florian Angeletti) + +- [#13203](https://github.com/ocaml/ocaml/issues/13203): Do not issue warning 53 if the compiler is stopping before attributes + have been accurately marked. + (Chris Casinghino, review by Florian Angeletti) + +- [#13207](https://github.com/ocaml/ocaml/issues/13207): Be sure to reload the register caching the exception handler in + caml_c_call and caml_c_call_stack_args, as its value may have been changed + if the OCaml stack is expanded during a callback. + (Miod Vallat, report by Vesa Karvonen, review by Gabriel Scherer and + Xavier Leroy) + +- [#13209](https://github.com/ocaml/ocaml/issues/13209): Fix configure test that checks whether `ar` supports `@FILE` + arguments. + (Nicolás Ojeda Bär, report by Boris D.) + +- [#13221](https://github.com/ocaml/ocaml/issues/13221): Compute more accurate instruction sizes for branch relocation on + POWER. + (Miod Vallat, review by Gabriel Scherer) + +- [#13252](https://github.com/ocaml/ocaml/issues/13252): Rework register assignment in the interpreter code on m68k on Linux, + due to the %a5 register being used by Glibc. + (Miod Vallat, report by Stéphane Glondu, review by Gabriel Scherer and + Xavier Leroy) + +- [#13247](https://github.com/ocaml/ocaml/issues/13247): Disable lib_unix/kill test for MacOS AMD64 with TSan, linking + to llvm bug report causing infinite signal loops. + (Tim McGilchrist, review by Olivier Nicole, Miod Vallat, Sébastien Hinderer + and Gabriel Scherer) + +- [#13234](https://github.com/ocaml/ocaml/issues/13234), [#13267](https://github.com/ocaml/ocaml/issues/13267): Open runtime events file in read-write mode on armel + (armv5) systems due to atomic operations limitations on that + platform. + (Stéphane Glondu, review by Miod Vallat and Vincent Laviron) + +- [#13273](https://github.com/ocaml/ocaml/issues/13273): Fix a call to test in configure.ac that was causing errors when + LDFLAGS contains several words. + (Stéphane Glondu, review by Miod Vallat) + +- [#13290](https://github.com/ocaml/ocaml/issues/13290): Fix uninitialized and out of bounds reads in runtime_events_consumer.c + (Edwin Török, review by Miod Vallat and Antonin Décimo) + +- [#13306](https://github.com/ocaml/ocaml/issues/13306): An algorithm in the type-checker that checks two types for equality + could sometimes, in theory, return the wrong answer. This patch fixes the + oversight. No known program triggers the bug. + (Richard Eisenberg, review by Florian Angeletti) + +- [#13400](https://github.com/ocaml/ocaml/issues/13400): Initialize th->signal_stack to avoid free of uninitialized data + if the user calls caml_c_thread_unregister on the main thread. + (Richard W.M. Jones, review by Guillaume Munch-Maccagnoni and + Gabriel Scherer) + +- [#13140](https://github.com/ocaml/ocaml/issues/13140): POWER back-end: fix issue with call to `caml_call_realloc_stack` + from a DLL + (Xavier Leroy, review by Miod Vallat) + +- [#13263](https://github.com/ocaml/ocaml/issues/13263), [#13560](https://github.com/ocaml/ocaml/issues/13560): fix printing true and false in toplevel and error + messages (no more unexpected \#true) + (Florian Angeletti, report by Samuel Vivien, review by Gabriel Scherer) + +- [#13388](https://github.com/ocaml/ocaml/issues/13388), [#13540](https://github.com/ocaml/ocaml/issues/13540): raises an error message (and not an internal compiler error) + when two local substitutions are incompatible (for instance `module type + S:=sig end type t:=(module S)`) + (Florian Angeletti, report by Nailen Matschke, review by Gabriel Scherer, and + Leo White) + +- [#13408](https://github.com/ocaml/ocaml/issues/13408): Fix misplaced debug runtime assertion triggerable by a race + between domain exit and backup thread + (Miod Vallat and Gabriel Scherer, report by Jan Midtgaard) + +- [#13417](https://github.com/ocaml/ocaml/issues/13417): `Filename.quote_command`: fix handling of forward slashes in program + path under Win32. + (Nicolás Ojeda Bär, review by David Allsopp and Damien Doligez) + +- [#13501](https://github.com/ocaml/ocaml/issues/13501): Regression on mutually recursive types caused by [#12180](https://github.com/ocaml/ocaml/issues/12180). + Resuscitate Typedecl.update_type. + (Jacques Garrigue and Takafumi Saikawa, review by Florian Angeletti, Richard + Eisenberg and Gabriel Scherer) + +- [#13502](https://github.com/ocaml/ocaml/issues/13502): Fix misindexing related to `Gc.finalise_last` that could prevent + finalisers from being run. + (Nick Roberts, review by Mark Shinwell) + +- [#13495](https://github.com/ocaml/ocaml/issues/13495), [#13514](https://github.com/ocaml/ocaml/issues/13514): Fix typechecker crash while typing objects + (Jacques Garrigue, report by Nicolás Ojeda Bär, review by + Nicolas Ojeda Bär, Gabriel Scherer, Stephen Dolan, Florian Angeletti) + +- [#13391](https://github.com/ocaml/ocaml/issues/13391), [#13551](https://github.com/ocaml/ocaml/issues/13551): fix a printing bug with `-dsource` when using + raw literal inside a locally abstract type constraint + (i.e. `let f: type \#for. ... `) + (Florian Angeletti, report by Nick Roberts, review by Richard Eisenberg) + +- [#13520](https://github.com/ocaml/ocaml/issues/13520): Fix compilation of native-code version of systhreads. Bytecode fields + were being included in the thread descriptors. + (David Allsopp, review by Sébastien Hinderer and Miod Vallat) + +- [#13541](https://github.com/ocaml/ocaml/issues/13541), [#13591](https://github.com/ocaml/ocaml/issues/13591): Fix headers for C++ inclusion. + (Antonin Décimo, review by Nick Barnes, report by Kate Deplaix) + +- [#13579](https://github.com/ocaml/ocaml/issues/13579), [#13583](https://github.com/ocaml/ocaml/issues/13583): Unsoundness involving non-injective types + gadts + (Jacques Garrigue, report by @v-gb, + review by Richard Eisenberg and Florian Angeletti) + +- [#13598](https://github.com/ocaml/ocaml/issues/13598): Falsely triggered warning 56 [unreachable-case] + This was caused by unproper protection of the retyping function. + (Jacques Garrigue, report by Tõivo Leedjärv, review by Florian Angeletti) + +- [#13603](https://github.com/ocaml/ocaml/issues/13603), [#13604](https://github.com/ocaml/ocaml/issues/13604): fix source printing in the presence of the escaped raw + identifier `\#mod`. + (Florian Angeletti, report by Chris Casinghino, review by Gabriel Scherer) diff --git a/data/tutorials/getting-started/1_00_install_OCaml.md b/data/tutorials/getting-started/1_00_install_OCaml.md index 43ad02acdb..e7b0c55b31 100644 --- a/data/tutorials/getting-started/1_00_install_OCaml.md +++ b/data/tutorials/getting-started/1_00_install_OCaml.md @@ -17,7 +17,7 @@ On this page, you'll find installation instructions for Linux, macOS, Windows, a OCaml has an official package manager, [opam](https://opam.ocaml.org/), which allows users to download and install OCaml tools and libraries. Opam also makes it practical to deal with different projects which require different versions of OCaml. -Opam also installs the OCaml compiler. Alternatives exist, but opam is the best way to install OCaml. Although OCaml is available as a package in most Linux distributions, it is often outdated. +Opam also installs the OCaml compiler. Alternatives exist, but opam is the best way to install OCaml. Although OCaml is available as a package in most Linux distributions, it is often outdated. To install opam, you can [use your system package manager](https://opam.ocaml.org/doc/Install.html#Using-your-distribution-39-s-package-system) or download the [binary distribution](https://opam.ocaml.org/doc/Install.html#Binary-distribution). The details are available in these links, but for convenience, we use package distributions: @@ -26,13 +26,13 @@ To install opam, you can [use your system package manager](https://opam.ocaml.or If you're installing with [Homebrew](https://brew.sh/): ```shell -$ brew install opam +brew install opam ``` Or if you're using [MacPorts](https://www.macports.org/): ```shell -$ port install opam +port install opam ``` **Note**: While it's rather straightforward to install opam using macOS, it's possible you'll run into problems later with Homebrew because it has changed the way it installs. The executable files cannot be found in ARM64, the M1 processor used in newer Macs. Addressing this can be a rather complicated procedure, so we've made [a short ARM64 Fix doc](/docs/arm64-fix) explaining this so as not to derail this installation guide. @@ -42,16 +42,19 @@ $ port install opam It's preferable to install opam with your system's package manager on Linux, as superuser. On the opam site, find [details of all installation methods](https://opam.ocaml.org/doc/Install.html). A version of opam above 2.0 is packaged in all supported Linux distributions. If you are using an unsupported Linux distribution, please either download a precompiled binary or build opam from sources. If you are installing in Debian or Ubuntu: + ```shell -$ sudo apt-get install opam +sudo apt-get install opam ``` If you are installing in Arch Linux: + ```shell -$ sudo pacman -S opam +sudo pacman -S opam ``` **Note**: The Debian package for opam, which is also used in Ubuntu, has the OCaml compiler as a recommended dependency. By default, such dependencies are installed. If you want to only install opam without OCaml, you need to run something like this: + ```shell sudo apt-get install --no-install-recommends opam ``` @@ -69,8 +72,9 @@ PS C:\> winget install Git.Git OCaml.opam If you want the latest release of opam, install it through the binary distribution. On Unix and macOS, you'll need to install the following system packages first: `gcc`, `build-essential`, `curl`, `bubblewrap`, and `unzip`. Note that they might have different names depending on your operating system or distribution. Also, note this script internally calls `sudo`. The following command will install the latest version of opam that applies to your system: + ```shell -$ bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh)" +bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh)" ``` On Windows, the winget package is maintained by opam's developers and uses the binaries released [on GitHub](https://github.com/ocaml/opam/releases), however you can also install using an equivalent PowerShell script: @@ -86,14 +90,15 @@ Invoke-Expression "& { $(Invoke-RestMethod https://opam.ocaml.org/install.ps1) } After you install opam, you'll need to initialise it. To do so, run the following command, as a normal user. This might take a few minutes to complete. ```shell -$ opam init -y +opam init -y ``` **Note**: In case you are running `opam init` inside a Docker container, you will need to disable sandboxing, which is done by running `opam init --disable-sandboxing -y`. This is necessary, unless you run a privileged Docker container. Make sure you follow the instructions provided at the end of the output of `opam init` to complete the initialisation. Typically, this is: + ``` -$ eval $(opam env) +eval $(opam env) ``` on Unix, and from the Windows Command Prompt: @@ -112,7 +117,7 @@ Opam initialisation may take several minutes. While waiting for its installation **Note**: opam can manage something called _switches_. This is key when switching between several OCaml projects. However, in this “getting started” series of tutorials, switches are not needed. If interested, you can read an introduction to [opam switches here](/docs/opam-switch-introduction). -**Any problems installing?** Be sure to read the [latest release notes](https://opam.ocaml.org/blog/opam-2-2-0/). You can file an issue at https://github.com/ocaml/opam/issues or https://github.com/ocaml-windows/papercuts/issues. +**Any problems installing?** Be sure to read the [latest release notes](https://opam.ocaml.org/blog/opam-2-2-0/). You can file an issue at or . ## Install Platform Tools @@ -125,8 +130,9 @@ Now that we've successfully installed the OCaml compiler and the opam package ma - [OCamlFormat](https://opam.ocaml.org/packages/ocamlformat/) to automatically format OCaml code All these tools can be installed using a single command: + ```shell -$ opam install ocaml-lsp-server odoc ocamlformat utop +opam install ocaml-lsp-server odoc ocamlformat utop ``` You're now all set and ready to start hacking. @@ -134,6 +140,7 @@ You're now all set and ready to start hacking. ## Check Installation To check that everything is working properly, you can start the UTop toplevel: + ```shell $ utop ────────┬─────────────────────────────────────────────────────────────┬───────── @@ -147,6 +154,7 @@ utop # ``` You're now in an OCaml toplevel, and you can start typing OCaml expressions. For instance, try typing `21 * 2;;` at the `#` prompt, then hit `Enter`. You'll see the following: + ```ocaml # 21 * 2;; - : int = 42 @@ -154,6 +162,8 @@ You're now in an OCaml toplevel, and you can start typing OCaml expressions. For **Congratulations**! You've installed OCaml! 🎉 +Exit UTop by typing `#quit;;` or pressing `Ctrl+D`. + ## Join the Community Make sure you [join the OCaml community](/community). You'll find many community members on [Discuss](https://discuss.ocaml.org/) or [Discord](https://discord.com/invite/cCYQbqN). These are great places to ask for help if you have any issues. diff --git a/data/tutorials/getting-started/1_01_a_tour_of_ocaml.md b/data/tutorials/getting-started/1_01_a_tour_of_ocaml.md index 3fd4fb48da..9b0f2fd704 100644 --- a/data/tutorials/getting-started/1_01_a_tour_of_ocaml.md +++ b/data/tutorials/getting-started/1_01_a_tour_of_ocaml.md @@ -49,6 +49,7 @@ The goal of this tutorial is to provide the following capabilities: ## Expressions and Definitions Let's start with a simple expression: + ```ocaml # 50 * 50;; - : int = 2500 @@ -59,6 +60,7 @@ In OCaml, everything has a value, and every value has a type. The above example The double semicolon `;;` at the end tells the toplevel to evaluate and print the result of the given phrase. Here are examples of other primitive values and types: + ```ocaml # 6.28;; - : float = 6.28 @@ -74,6 +76,7 @@ Here are examples of other primitive values and types: ``` OCaml has _type inference_. It automatically determines the type of an expression without much guidance from the programmer. _Lists_ have a [dedicated tutorial](/docs/lists). For the time being, the following two expressions are both lists. The former contains integers, and the latter, strings. + ```ocaml # let u = [1; 2; 3; 4];; val u : int list = [1; 2; 3; 4] @@ -83,12 +86,14 @@ val u : int list = [1; 2; 3; 4] ``` The lists' types, `int list` and `string list`, have been inferred from the type of their elements. Lists can be empty `[]` (pronounced “nil”). Note that the first list has been given a name using the `let … = …` construction, which is detailed below. The most primitive operation on lists is to add a new element at the front of an existing list. This is done using the “cons” operator, written with the double colon operator `::`. + ```ocaml # 9 :: u;; - : int list = [9; 1; 2; 3; 4] ``` In OCaml, `if … then … else …` is not a statement; it is an expression. + ```ocaml # 2 * if "hello" = "world" then 3 else 5;; - : int = 10 @@ -97,6 +102,7 @@ In OCaml, `if … then … else …` is not a statement; it is an expression. The source beginning at `if` and ending at `5` is parsed as a single integer expression that is multiplied by 2. OCaml has no need for two different test constructions. The [ternary conditional operator](https://en.wikipedia.org/wiki/Ternary_conditional_operator) and the `if … then … else …` are the same. Also note parentheses are not needed here, which is often the case in OCaml. Values can be given names using the `let` keyword. This is called _binding_ a value to a name. For example: + ```ocaml # let x = 50;; val x : int = 50 @@ -124,6 +130,7 @@ val feets : int = 5280 This is discussed further in [`odoc` for Authors: Special Comments](https://ocaml.github.io/odoc/odoc_for_authors.html#special_comments). Names can be defined locally, within an expression, using the `let … = … in …` syntax: + ```ocaml # let y = 50 in y * y;; - : int = 2500 @@ -135,6 +142,7 @@ Error: Unbound value y This example defines the name `y` and binds it to the value `50`. It is then used in the expression `y * y`, resulting in the value `2500`. Note that `y` is only defined in the expression following the `in` keyword. Since `let … = … in …` is an expression, it can be used within another expression in order to have several values with their own names: + ```ocaml # let a = 1 in let b = 2 in @@ -145,6 +153,7 @@ Since `let … = … in …` is an expression, it can be used within another exp This defines two names: `a` with value `1` and `b` with value `2`. Then the example uses them in the expression `a + b`, resulting in the value of `3`. In OCaml, the equality symbol has two meanings. It is used in definitions and equality tests. + ```ocaml # let dummy = "hi" = "hello";; val dummy : bool = false @@ -155,6 +164,7 @@ This is interpreted as: “define `dummy` as the result of the structural equali ## Functions In OCaml, since everything is a value, functions are values too. Functions are defined using the `let` keyword: + ```ocaml # let square x = x * x;; val square : int -> int = @@ -177,17 +187,19 @@ The REPL indicates that the type of `square` is `int -> int`. This means it is a - : bool = true ``` -Some functions, such as `String.ends_with` have labelled parameters. Labels are useful when a function has several parameters of the same type; naming arguments allows to guess their purpose. Above, `~suffix:"less"` indicates `"less"` is passed as labelled argument `suffix`. Labelled arguments are detailed in the [Labelled Arguments](/docs/labels) tutorial. +Some functions, such as `String.ends_with` have labelled parameters. Labels are useful when a function has several parameters of the same type; naming arguments allows to guess their purpose. Above, `~suffix:"less"` indicates `"less"` is passed as labelled argument `suffix`. Labelled arguments are detailed in the [Labelled Arguments](/docs/labels) tutorial. ### Anonymous Functions _Anonymous_ functions do not have a name, and they are defined with the `fun` keyword: + ```ocaml # fun x -> x * x;; - : int -> int = ``` We can write anonymous functions and immediately apply them to a value: + ```ocaml # (fun x -> x * x) 50;; - : int = 2500 @@ -196,18 +208,21 @@ We can write anonymous functions and immediately apply them to a value: ### Functions with Multiple Parameters and Partial Application A function may have several parameters, separated by spaces. + ```ocaml # let cat a b = a ^ " " ^ b;; val cat : string -> string -> string = ``` The function `cat` has two `string` parameters, `a` and `b`, and returns a value of type `string`. + ```ocaml # cat "ha" "ha";; - : string = "ha ha" ``` Functions don't have to be called with all the arguments they expect. It is possible to only pass `a` to `cat` without passing `b`. + ```ocaml # let cat_hi = cat "hi";; val cat_hi : string -> string = @@ -216,6 +231,7 @@ val cat_hi : string -> string = This returns a function that expects a single string, here the `b` from the definition of `cat`. This is called a _partial application_. In the above, `cat` was partially applied to `"hi"`. The function `cat_hi`, which resulted from the partial application of `cat`, behaves as follows: + ```ocaml # cat_hi "friend";; - : string = "hi friend" @@ -224,6 +240,7 @@ The function `cat_hi`, which resulted from the partial application of `cat`, beh ### Type Parameters and Higher-Order Functions A function may expect a function as a parameter, which is called a _higher-order_ function. A well-known example of higher-order function is `List.map`. Here is how it can be used: + ```ocaml # List.map;; - : ('a -> 'b) -> 'a list -> 'b list = @@ -245,6 +262,7 @@ The function `List.map` can be applied on any kind of list. Here it is given a l ### Side-Effects and the `unit` Type Performing operating system level input-output operations is done using functions. Here is an example of each: + ```ocaml # read_line;; - : unit -> string = @@ -272,6 +290,7 @@ Input-output is an example of something taking place when executing a function b A recursive function calls itself in its own body. Such functions must be declared using `let rec … = …` instead of just `let`. Recursion is not the only means to perform iterative computation on OCaml. Loops such as `for` and `while` are available, but they are meant to be used when writing imperative OCaml in conjunction with mutable data. Otherwise, recursive functions should be preferred. Here is an example of a function which creates a list of consecutive integers between two bounds. + ```ocaml # let rec range lo hi = if lo > hi then @@ -303,6 +322,7 @@ Each `=>` sign corresponds to the computation of a recursive step, except the la ### Type Conversion and Type-Inference OCaml has floating-point values of type `float`. To add floats, one must use `+.` instead of `+`: + ```ocaml # 2.0 +. 2.0;; - : float = 4. @@ -313,6 +333,7 @@ In OCaml, `+.` is the addition between floats, while `+` is the addition between In many programming languages, values can be automatically converted from one type into another. This includes _implicit type conversion_ and _promotion_. For example, in such a language, if you write `1 + 2.5`, the first argument (an integer) is promoted to a floating point number, making the result a floating point number, too. OCaml never implicitly converts values from one type to another. It is not possible to perform the addition of a float and integer. Both examples below throw an error: + ```ocaml # 1 + 2.5;; Error: This expression has type float but an expression was expected of type @@ -323,9 +344,11 @@ Error: This expression has type int but an expression was expected of type float Hint: Did you mean `1.'? ``` + In the first example, `+` is intended to be used with integers, so it can't be used with the `2.5` float. In the second example, `+.` is intended to be used with floats, so it can't be used with the `1` integer. In OCaml you need to explicitly convert the integer to a floating point number using the `float_of_int` function: + ```ocaml # float_of_int 1 +. 2.5;; - : float = 3.5 @@ -336,6 +359,7 @@ There are several reasons why OCaml requires explicit conversions. Most importan ### Lists Lists may be the most common data type in OCaml. They are ordered collections of values having the same type. Here are a few examples. + ```ocaml # [];; - : 'a list = [] @@ -351,18 +375,21 @@ Lists may be the most common data type in OCaml. They are ordered collections of ``` The examples above read the following way: + 1. The empty list, nil 1. A list containing the numbers 1, 2, and 3 1. A list containing the Booleans `false`, `false`, and `true`. Repetitions are allowed. 1. A list of lists Lists are defined as being either empty, written `[]`, or being an element `x` added at the front of another list `u`, which is written `x :: u` (the double colon operator is pronounced “cons”). + ```ocaml # 1 :: [2; 3; 4];; - : int list = [1; 2; 3; 4] ``` In OCaml, _pattern matching_ provides a means to inspect data of any kind, except functions. In this section, it is introduced on lists, and it will be generalised to other data types in the next section. Here is how pattern matching can be used to define a recursive function that computes the sum of a list of integers: + ```ocaml # let rec sum u = match u with @@ -373,10 +400,12 @@ val sum : int list -> int = # sum [1; 4; 3; 2; 5];; - : int = 15 ``` +Note that the `x :: v` pattern in the second matching expression is used to destructure the list into its head `x` and tail `v`, where _head_ is the first element of the list and _tail_ is the rest of the list. #### Polymorphic Functions on Lists Here is how to write a recursive function that computes the length of a list: + ```ocaml # let rec length u = match u with @@ -399,6 +428,7 @@ This function operates not just on lists of integers but on any kind of list. It #### Defining a Higher-Order Function It is possible to pass a function as argument to another function. Functions having other functions as parameters are called _higher-order_ functions. This was illustrated earlier using function `List.map`. Here is how `map` can be written using pattern matching on lists. + ```ocaml # let square x = x * x;; val square : int -> int @@ -416,6 +446,7 @@ val map : ('a -> 'b) -> 'a list -> 'b list = ### Pattern Matching, Cont'd Pattern matching isn't limited to lists. Any kind of data can be inspected using it, except functions. Patterns are expressions that are compared to an inspected value. It could be performed using `if … then … else …`, but pattern matching is more convenient. Here is an example using the `option` data type that will be detailed in the [Modules and the Standard Library](#modules-and-the-standard-library) section. + ```ocaml # #show option;; type 'a option = None | Some of 'a @@ -432,6 +463,7 @@ The inspected value is `opt` of type `option`. It is compared against the patter Pattern matching is detailed in the [Basic Datatypes](/docs/basic-data-types) tutorial as well as in per data type tutorials. In this other example, the same comparison is made, using `if … then … else …` and pattern matching. + ```ocaml # let g x = if x = "foo" then 1 @@ -453,6 +485,7 @@ val g' : string -> int = The underscore symbol is a catch-all pattern; it matches with anything. Note that OCaml throws a warning when pattern matching does not catch all cases: + ```ocaml # fun i -> match i with 0 -> 1;; Line 1, characters 9-28: @@ -465,6 +498,7 @@ Here is an example of a case that is not matched: ### Pairs and Tuples Tuples are fixed-length collections of elements of any type. Pairs are tuples that have two elements. Here is a 3-tuple and a pair: + ```ocaml # (1, "one", 'K');; - : int * string * char = (1, "one", 'K') @@ -474,6 +508,7 @@ Tuples are fixed-length collections of elements of any type. Pairs are tuples th ``` Access to the components of tuples is done using pattern matching. For instance, the predefined function `snd` returns the second component of a pair: + ```ocaml # let snd p = match p with @@ -493,6 +528,7 @@ The type of tuples is written using `*` between the components' types. Like pattern matching generalises `switch` statements, variant types generalise enumerated and union types. Here is the definition of a variant type acting as an enumerated data type: + ```ocaml # type primary_colour = Red | Green | Blue;; type primary_colour = Red | Green | Blue @@ -502,6 +538,7 @@ type primary_colour = Red | Green | Blue ``` Here is the definition of a variant type acting as a union type: + ```ocaml # type http_response = | Data of string @@ -528,6 +565,7 @@ Data ``` Here is something sitting in between: + ```ocaml # type page_range = | All @@ -539,6 +577,7 @@ type page_range = All | Current | Range of int * int In the previous definitions, the capitalised identifiers are called _constructors_. They allow the creation of variant values. This is unrelated to object-oriented programming. As suggested in the first sentence of this section, variants go along with pattern matching. Here are some examples: + ```ocaml # let colour_to_rgb colour = match colour with @@ -562,6 +601,7 @@ val is_printable : int -> int -> page_range -> bool = ``` Like a function, a variant can be recursive if it refers to itself in its own definition. The predefined type `list` provides an example of such a variant: + ```ocaml # #show list;; type 'a list = [] | (::) of 'a * 'a list @@ -572,6 +612,7 @@ As previously shown, `sum`, `length`, and `map` functions provide examples of pa ### Records Like tuples, records also pack elements of several types together. However, each element is given a name. Like variant types, records types must be defined before being used. Here are examples of a record type, a value, access to a component, and pattern matching on the same record. + ```ocaml # type person = { first_name : string; @@ -589,6 +630,7 @@ val gerard : person = {first_name = "Gérard"; surname = "Huet"; age = 76} ``` When defining `gerard`, no type needs to be declared. The type checker will search for a record which has exactly three fields with matching names and types. Note that there are no typing relationships between records. It is not possible to declare a record type that extends another by adding fields. Record type search will succeed if it finds an exact match and fails in any other case. + ```ocaml # let s = gerard.surname;; val s : string = "Huet" @@ -609,12 +651,14 @@ Here, the pattern `{ age = x; _ }` is typed with the most recently declared reco ### Exceptions When a computation is interrupted, an exception is thrown. For instance: + ```ocaml # 10 / 0;; Exception: Division_by_zero. ``` Exceptions are raised using the `raise` function. + ```ocaml # let id_42 n = if n <> 42 then raise (Failure "Sorry") else n;; val id_42 : int -> int = @@ -629,6 +673,7 @@ Exception: Failure "Sorry". Note that exceptions do not appear in function types. Exceptions are caught using the `try … with …` construction: + ```ocaml # try id_42 0 with Failure _ -> 0;; - : int = 0 @@ -640,12 +685,14 @@ The standard library provides several predefined exceptions. It is possible to d Another way to deal with errors in OCaml is by returning value of type `result`, which can represent either the correct result or an error. Here is how it is defined: + ```ocaml # #show result;; type ('a, 'b) result = Ok of 'a | Error of 'b ``` So one may write: + ```ocaml # let id_42_res n = if n <> 42 then Error "Sorry" else Ok n;; val id_42_res : int -> (int, string) result = @@ -665,6 +712,7 @@ val id_42_res : int -> (int, string) result = ## Working with Mutable State OCaml supports imperative programming. Usually, the `let … = …` syntax does not define variables, it defines constants. However, mutable variables exist in OCaml. They are called _references_. Here's how we create a reference to an integer: + ```ocaml # let r = ref 0;; val r : int ref = {contents = 0} @@ -673,6 +721,7 @@ val r : int ref = {contents = 0} It is syntactically impossible to create an uninitialised or null reference. The `r` reference is initialised with the integer zero. Accessing a reference's content is done using the `!` de-reference operator. + ```ocaml # !r;; - : int = 0 @@ -684,18 +733,21 @@ it is not possible to update an integer or multiply a reference. Let's update the content of `r`. Here `:=` is the assignment operator; it is pronounced “receives”. + ```ocaml # r := 42;; - : unit = () ``` This returns `()` because changing the content of a reference is a side-effect. + ```ocaml # !r;; - : int = 42 ``` Execute an expression after another with the `;` operator. Writing `a; b` means: execute `a`. Once done, execute `b`, only returns the value of `b`. + ```ocaml # let text = ref "hello ";; val text : string ref = {contents = "hello "} @@ -706,6 +758,7 @@ hello world! ``` Here are the side effects that occur in the second line: + 1. Display the contents of the reference `text` on standard output 1. Update the contents of the reference `text` 1. Display the contents of the reference `text` on standard output @@ -715,6 +768,7 @@ This behaviour is the same as in an imperative language. However, although `;` i ## Modules and the Standard Library Organising source code in OCaml is done using something called _modules_. A module is a group of definitions. The _standard library_ is a set of modules available to all OCaml programs. Here are how the definitions contained in the `Option` module of the standard library can be listed: + ```ocaml # #show Option;; module Option : @@ -740,6 +794,7 @@ module Option : ``` Definitions provided by modules are referred to by adding the module name as a prefix to their name. + ```ocaml # Option.map;; - : ('a -> 'b) -> 'a option -> 'b option = @@ -755,6 +810,7 @@ Definitions provided by modules are referred to by adding the module name as a p ``` Here, usage of the function `Option.map` is illustrated in several steps. + 1. Display its type. It has two parameters: a function of type `'a -> 'b` and an `'a option`. 1. Using partial application, only pass `fun x -> x * x`. Check the type of the resulting function. 1. Apply with `None`. @@ -763,6 +819,7 @@ Here, usage of the function `Option.map` is illustrated in several steps. When the option value provided contains an actual value (i.e., it is `Some` something), it applies the provided function and returns its result wrapped in an option. When the option value provided doesn't contain anything (i.e., it is `None`), the result doesn't contain anything as well (i.e., it is `None` too). The `List.map` function which was used earlier in this section is also part of a module, the `List` module. + ```ocaml # List.map;; - : ('a -> 'b) -> 'a list -> 'b list = diff --git a/data/tutorials/getting-started/1_02_your_first_ocaml_program.md b/data/tutorials/getting-started/1_02_your_first_ocaml_program.md index 96e9577c87..3173098a70 100644 --- a/data/tutorials/getting-started/1_02_your_first_ocaml_program.md +++ b/data/tutorials/getting-started/1_02_your_first_ocaml_program.md @@ -28,7 +28,6 @@ Once you've completed this tutorial, you should be able to: - Make a definition private - Download, install, and use a package from the open source repository - How to work on several OCaml projects simultaneously is out of the scope of this tutorial. Currently (Summer 2023), this requires using opam local [_switches_](https://opam.ocaml.org/doc/man/opam-switch.html). This allows handling different sets of dependencies per project. Check the Best Practices document on [Dependencies](https://ocaml.org/docs/managing-dependencies) addressing that matter for detailed instructions. This document was written and tested using a global switch, which is created by default when installing opam and can be ignored in the beginning. --> @@ -57,15 +56,10 @@ Success: initialized project component named hello **Note 2**: Throughout this tutorial, outputs generated by Dune might vary slightly because of the Dune version installed. This tutorial shows the output for Dune 3.12. If you'd like to get the most recent version of Dune, run `opam update; opam upgrade dune` in a terminal. -The project is stored in a directory named `hello`. The `tree` command lists the files and directories created. It might be necessary to install `tree` if you don't see the following. Through Homebrew, for example, run `brew install tree`. - -**Note 3**: If you get an error in Homebrew from this in an Apple silicon macOS, it's likely an issue with the architecture switch from Intel to ARM. Please refer to the [ARM64 Fix](/docs/arm64-fix) to remedy the ARM64 error. +The project is stored in a directory named `hello` with the following contents: -**Note 4**: Unlike in Unix where they contain compiled binaries, directories `lib` and `bin` contain source code files, for libraries and programs, respectively. This is the a convention used in many OCaml projects, and the canned project created by Dune. All the built artifacts, and a copy of the sources, are stored in the `_build` directory. You shall not edit anything in the `_build` directory. ```shell -$ cd hello -$ tree -. +hello ├── bin │ ├── dune │ └── main.ml @@ -78,11 +72,12 @@ $ tree └── test ├── dune └── hello.ml - -4 directories, 8 files ``` +Unlike in Unix where they contain compiled binaries, directories `lib` and `bin` contain source code files, for libraries and programs, respectively. This is the convention used in many OCaml projects, including those created by Dune. All the built artifacts, and a copy of the sources, are stored in the `_build` directory. Do not edit anything in the `_build` directory, since any manual edits will be overwritten during subsequent builds. + OCaml source files have the `.ml` extension, which stands for “Meta Language.” Meta Language (ML) is an ancestor of OCaml. This is also what the “ml” stands for in “OCaml.” Here is the content of the `bin/main.ml` file: + ```ocaml let () = print_endline "Hello, World!" ``` @@ -92,11 +87,13 @@ The project-wide metadata is available in the `dune-project` file. It contains i Each directory containing source files that need to be built must contain a `dune` file describing how. This builds the project: + ```shell -$ opam exec -- dune build +opam exec -- dune build ``` This launches the executable it creates: + ```shell $ opam exec -- dune exec hello Hello, World! @@ -113,8 +110,8 @@ In the rest of this tutorial, we will make more changes to this project in order Before we dive in, note that you will typically want to use Dune's watch mode to continually compile and optionally restart your program. This ensures that the language server has the freshest possible data about your project, so your editor support will be top-notch. To use watch mode, just add the `-w` flag: ```shell -$ opam exec -- dune build -w -$ opam exec -- dune exec hello -w +opam exec -- dune build -w +opam exec -- dune exec hello -w ``` ## Why Isn't There a Main Function? @@ -128,11 +125,13 @@ However, it is common practice to single out a value that triggers all the side ## Modules and the Standard Library, Cont'd Let's summarise what was said about modules in the [Tour of OCaml](/docs/tour-of-ocaml): + - A module is a collection of named values. - Identical names from distinct modules don't clash. -- The standard library is collection of several modules. +- The standard library is a collection of several modules. Modules aid in organising projects; concerns can be separated into isolated modules. This is outlined in the next section. Before creating a module ourselves, we'll demonstrate using a definition from a module of the standard library. Change the content of the file `bin/main.ml` to this: + ```ocaml let () = Printf.printf "%s\n" "Hello, World!" ``` @@ -144,16 +143,19 @@ This replaces the function `print_endline` with the function `printf` from the ` Each OCaml file defines a module, once compiled. This is how separate compilation works in OCaml. Each sufficiently standalone concern should be isolated into a module. References to external modules create dependencies. Circular dependencies between modules are not allowed. To create a module, let's create a new file named `lib/en.ml` containing this: + ```ocaml let v = "Hello, world!" ``` Here is a new version of the `bin/main.ml` file: + ```ocaml let () = Printf.printf "%s\n" Hello.En.v ``` Now execute the resulting project: + ```shell $ opam exec -- dune exec hello Hello, world! @@ -161,13 +163,14 @@ Hello, world! The file `lib/en.ml` creates the module named `En`, which in turn defines a string value named `v`. Dune wraps `En` into another module called `Hello`; this name is defined by the stanza `name hello` in the file `lib/dune`. The string definition is `Hello.En.v` from the `bin/main.ml` file. - Dune can launch UTop to access the modules exposed by a project interactively. Here's how: + ```shell -$ opam exec -- dune utop +opam exec -- dune utop ``` Then, inside the `utop` toplevel, it is possible to inspect our `Hello.En` module: + ```ocaml # #show Hello.En;; module Hello : sig val v : string end @@ -176,6 +179,7 @@ module Hello : sig val v : string end Now exit `utop` with `Ctrl-D` or enter `#quit;;` before going to the next section. **Note**: If you add a file named `hello.ml` in the `lib` directory, Dune will consider this the whole `Hello` module and it will make `En` unreachable. If you want your module `En` to be visible, you need to add this in your `hello.ml` file: + ```ocaml module En = En ``` @@ -184,6 +188,7 @@ module En = En ## Defining Module Interfaces UTop's `#show` command displays an [API](https://en.wikipedia.org/wiki/API#Libraries_and_frameworks) (in the software library sense): the list of definitions provided by a module. In OCaml, this is called a _module interface_. An `.ml` file defines a module. In a similar way, an `.mli` file defines a module interface. The module interface file corresponding to a module file must have the same base name, e.g., `en.mli` is the module interface for module `en.ml`. Create a `lib/en.mli` file with this content: + ```ocaml val v : string ``` @@ -200,11 +205,13 @@ let v = hello ^ ", world!" ``` Also edit the `bin/main.ml` file like this: + ```ocaml let () = Printf.printf "%s\n" Hello.En.hello ``` Trying to compile this fails. + ```shell $ opam exec -- dune build File "hello/bin/main.ml", line 1, characters 30-43: @@ -217,6 +224,7 @@ This is because we haven't changed `lib/en.mli`. Since it does not list `hello`, it is therefore private. ## Defining Multiple Modules in a Library + Multiple modules can be defined in a single library. To demonstrate this, create a new file named `lib/es.ml` with the following content: @@ -225,6 +233,7 @@ let v = "¡Hola, mundo!" ``` And use the new module in `bin/main.ml`: + ```ocaml let () = Printf.printf "%s\n" Hello.Es.v let () = Printf.printf "%s\n" Hello.En.v @@ -246,8 +255,9 @@ A more detailed introduction to modules can be found at [Modules](/docs/modules) OCaml has an active community of open-source contributors. Most projects are available using the opam package manager, which you installed in the [Install OCaml](/docs/up-and-ready) tutorial. The following section shows you how to install and use a package from opam's open-source repository. To illustrate this, let's update our `hello` project to parse a string containing an [S-expression](https://en.wikipedia.org/wiki/S-expression) and print back to a string, both using [Sexplib](https://github.com/janestreet/sexplib). First, update the package list for opam by running `opam update`. Then, install the `Sexplib` package with this command: + ```shell -$ opam install sexplib +opam install sexplib ``` Next, define a string containing a valid S-expression in `bin/main.ml`. Parse @@ -263,8 +273,9 @@ let exp1 = Sexplib.Sexp.of_string "(This (is an) (s expression))" (* Convert back to a string to print *) let () = Printf.printf "%s\n" (Sexplib.Sexp.to_string exp1) ``` + The string you entered representing a valid S-expression is parsed into -an S-expression type, which is defined as either an `Atom` (string) or a `List` +an S-expression type, which is defined as either an `Atom` (string) or a `List` of S-expressions (it's a recursive type). Refer to the [Sexplib documentation](https://github.com/janestreet/sexplib) for more information. Before the example will build and run, you need to tell Dune that it needs `Sexplib` to compile the project. Do this by adding `Sexplib` to the `library` stanza of the `bin/dune` file. The full `bin/dune` file should then match the following. @@ -279,6 +290,7 @@ Before the example will build and run, you need to tell Dune that it needs `Sexp **Fun fact**: Dune configuration files are S-expressions. Finally, execute as before: + ```shell $ opam exec -- dune exec hello (This(is an)(s expression)) @@ -290,11 +302,13 @@ $ opam exec -- dune exec hello **Note**: This example was successfully tested on Windows using DkML 2.1.0. Run `dkml version` to see the version. Let's assume we'd like `hello` to display its output as if it was a list of strings in UTop: `["hello"; "using"; "an"; "opam"; "library"]`. To do that, we need a function turning a `string list` into a `string`, adding brackets, spaces, and commas. Instead of defining it ourselves, let's generate it automatically with a package. We'll use [`ppx_deriving`](https://github.com/ocaml-ppx/ppx_deriving). Here is how to install it: + ```shell -$ opam install ppx_deriving +opam install ppx_deriving ``` Dune needs to be told how to use it, which is done in the `lib/dune` file. Note that this is different from the `bin/dune` file that you edited earlier! Open up the `lib/dune` file, and edit it to look like this: + ```lisp (library (name hello) @@ -306,12 +320,14 @@ The line `(preprocess (pps ppx_deriving.show))` means that before compilation th The files `lib/en.ml` and `lib/en.mli` need to be edited, too: **`lib/en.mli`** + ```ocaml val string_of_string_list : string list -> string val v : string list ``` **`lib/en.ml`** + ```ocaml let string_of_string_list = [%show: string list] @@ -319,15 +335,18 @@ let v = String.split_on_char ' ' "Hello using an opam library" ``` Let's read this from the bottom up: + - `v` has the type `string list`. We're using `String.split_on_char` to turn a `string` into a `string list` by splitting the string on space characters. - `string_of_string_list` has type `string list -> string`. This converts a list of strings into a string, applying the expected formatting. Finally, you'll also need to edit `bin/main.ml` + ```ocaml let () = print_endline Hello.En.(string_of_string_list v) ``` Here is the result: + ```shell $ opam exec -- dune exec hello ["Hello"; "using"; "an"; "opam"; "library"] @@ -338,11 +357,13 @@ $ opam exec -- dune exec hello This section explains the purpose of the files and directories created by `dune init proj` which haven't been mentioned earlier. Along the history of OCaml, several build systems have been used. As of writing this tutorial (Summer 2023), Dune is the mainstream one, which is why it is used in the tutorial. Dune automatically extracts the dependencies between the modules from the files and compiles them in a compatible order. It only needs one `dune` file per directory where there is something to build. The three directories created by `dune init proj` have the following purposes: + - `bin`: executable programs - `lib`: libraries - `test`: tests There will be a tutorial dedicated to Dune. This tutorial will present the many features of Dune, a few of which are listed here: + - Running tests - Generating documentation - Producing packaging metadata (here in `hello.opam`) @@ -353,30 +374,35 @@ The `_build` directory is where Dune stores all the files it generates. It can b ## Minimum Setup In this last section, let's create a bare minimum project, highlighting what's really needed for Dune to work. We begin by creating a fresh project directory: + ```shell -$ cd .. -$ mkdir minimo -$ cd minimo +cd .. +mkdir minimo +cd minimo ``` At the very least, Dune only needs two files: `dune-project` and one `dune` file. Here is how to write them with as little text as possible: `dune-project` + ```lisp (lang dune 3.6) ``` `dune` + ```lisp (executable (name minimo)) ``` `minimo.ml` + ```ocaml let () = print_endline "My name is Minimo" ``` That's all! This is sufficient for Dune to build and execute the `minimo.ml` file. + ```shell $ opam exec -- dune exec ./minimo.exe My name is Minimo diff --git a/data/tutorials/getting-started/2_00_editor_setup.md b/data/tutorials/getting-started/2_00_editor_setup.md index 53f8b076e7..73c106ab2a 100644 --- a/data/tutorials/getting-started/2_00_editor_setup.md +++ b/data/tutorials/getting-started/2_00_editor_setup.md @@ -16,26 +16,28 @@ OCaml has plugins for many editors, but the most actively maintained are for Vis For VSCode, install the [OCaml Platform Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=ocamllabs.ocaml-platform) from the Visual Studio Marketplace. The extension depends on OCaml LSP and OCamlFormat. To install them in your switch, you can run: ```shell -$ opam install ocaml-lsp-server ocamlformat +opam install ocaml-lsp-server ocamlformat ``` -Upon first loading an OCaml source file, you may be prompted to select the toolchain in use. Pick the version of OCaml you are using, e.g., `5.1.0` from the list. +Upon first loading an OCaml source file, you may be prompted to select the toolchain in use. Pick the version of OCaml you are using, e.g., `5.1.0` from the list. ### Editor Features at Your Disposal + If your editor is setup correctly, here are some important features you can begin using to your advantage: -#### 1) Hovering for Type Information: + +#### 1) Hovering for Type Information ![VSCode Hovering](/media/tutorials/vscode-hover.gif) This is a great feature that let's you see type information of any OCaml variable or function. All you have to do is place your cursor over the code and it will be displayed in the tooltip. -#### 2) Jump to Definitions With `Ctrl + Click`: +#### 2) Jump to Definitions With `Ctrl + Click` ![VSCode Ctrl click](/media/tutorials/vscode-ctrl-click.gif) If you hold down the Ctrl key while hovering, the code appears as a clickable link which if clicked takes you to the file where the implementation is. This can be great if you want to understand how a piece of code works under the hood. In this example, hovering and `Ctrl + Clicking` over the `peek` method of the `Queue` module will take you to the definiton of the `peek` method itself and how it is implemented. -#### 3) OCaml Commands With `Ctrl + Shift + P`: +#### 3) OCaml Commands With `Ctrl + Shift + P` ![VSCode OCaml Commands](/media/tutorials/vscode-ocaml-commands.gif) @@ -47,27 +49,95 @@ If you used the DkML distribution, you will need to: 1. Go to `File` > `Preferences` > `Settings` view (or press `Ctrl ,`) 2. Select `User` > `Extensions` > `OCaml Platform` 3. Uncheck `OCaml: Use OCaml Env`. That's it! + +## Emacs + +Using Emacs to work with OCaml requires at least two modes: + +- A major mode, which, among other things, supports syntax highlighting and the structuring of indentation levels +- A minor mode, which will interact with a language server (such as `ocaml-lsp-server` or `merlin`). In this tutorial, we will focus on using the new `ocaml-eglot` mode and `ocaml-lsp-server` as a server. + +### Choosing a major mode + +There are several major modes dedicated to OCaml, of which the 3 main ones are: + +- [Tuareg](https://github.com/ocaml/tuareg): an old-fashioned (but still updated), very complete mode, usually the recommended one +- [Caml](https://github.com/ocaml/caml-mode): a mode even older than `tuareg` (but still updated), lighter than `tuareg` +- [Neocaml](https://github.com/bbatsov/neocaml): a brand new mode, based on modern tools (like [tree-sitter](https://tree-sitter.github.io/tree-sitter/)). Still experimental at the time of writing. + +For the purposes of this tutorial, we are going to focus on the use of `tuareg` as the major mode, but you should feel free to experiment and choose your favourite one! To use `tuareg`, you can add these lines to your Emacs configuration: + +```elisp +(use-package tuareg + :ensure t + :mode (("\\.ocamlinit\\'" . tuareg-mode))) +``` + + +#### Melpa and `use-package` + +If your version of Emacs does not support the `use-package` macro (or is not set up to take MELPA packages into account), please update it and follow these instructions to install [`use-package`](https://github.com/jwiegley/use-package) and [MELPA](https://melpa.org/#/getting-started). + +### LSP setup for OCaml + +Since version `29.1`, Emacs has had a built-in mode for interacting with LSP servers, [Eglot](https://www.gnu.org/software/emacs/manual/html_mono/eglot.html). If you are using an earlier version of Emacs, you will need to install it this way: + +```elisp +(use-package eglot + :ensure t) +``` + +Next, we need to bridge the gap between our major mode (in this case, `tuareg`) and `eglot`. This is done using the [`ocaml-eglot`](https://github.com/tarides/ocaml-eglot) package: + +```elisp +(use-package ocaml-eglot + :ensure t + :after tuareg + :hook + (tuareg-mode . ocaml-eglot) + (ocaml-eglot . eglot-ensure)) +``` -## Vim and Emacs +And that's all there is to it! Now all you need to do is install `ocaml-lsp-server` and `ocamlformat` in our [switch](/docs/opam-switch-introduction): -**For Vim and Emacs**, we won't use the LSP server but rather directly talk to Merlin. +```shell +opam install ocaml-lsp-server ocamlformat +``` + +You are now ready to edit OCaml code _productively_ with Emacs! + +#### Finer configuration + +OCaml-eglot can be finely configured, the project [README](https://github.com/tarides/ocaml-eglot/blob/main/README.md) gives several configuration paths to adapt perfectly to your workflow. You will also find there an exhaustive presentation of the different functions offered by the mode. + + +#### Getting Type Information + +Opening an OCaml file should launch an `ocaml-lsp` server, and you can convince yourself that it's working by using, for example, the `ocaml-eglot-type-enclosing` command (or using the `C-c C-t` binding) on an expression of your choice: + +![Emacs Type information](/media/tutorials/emacs-type-info.gif) + +OCaml-eglot [README](https://github.com/tarides/ocaml-eglot/blob/main/README.md) provides a comprehensive overview of all the functions available in this mode! + + +## Vim + +For Vim, we won't use the LSP server but rather directly talk to Merlin. ```shell -$ opam install merlin +opam install merlin ``` After installing Merlin above, instructions will be printed on how to link Merlin with your editor. If you do not have them visible, just run this command: ```shell -$ opam user-setup install +opam user-setup install ``` ### Talking to Merlin #### Getting Type Information -**Vim** - ![Vim Type information](/media/tutorials/vim-type-info.gif) - In the Vim editor, press the Esc to enter command mode. @@ -75,12 +145,3 @@ $ opam user-setup install - Type `:MerlinTypeOf` and press Enter. - The type information will be displayed in the command bar. Other Merlin commands for Vim are available and you can checkout their usage on the [Merlin official documentation for Vim](https://ocaml.github.io/merlin/editor/vim/). - -**Emacs** - -![Emacs Type information](/media/tutorials/emacs-type-info.gif) - -- In the Emacs editor, place you cursor over the variable. -- Use the keyboard shortcut Alt + x followed by `merlin-type-enclosing` -- The type information will be displayed in the mini-buffer. -Other Merlin commands for Emacs are available and you can checkout their usage on the [Merlin Official documentation for Emacs](https://ocaml.github.io/merlin/editor/emacs/). diff --git a/data/tutorials/getting-started/2_01_toplevel.md b/data/tutorials/getting-started/2_01_toplevel.md index 59b618446e..ac10339ca9 100644 --- a/data/tutorials/getting-started/2_01_toplevel.md +++ b/data/tutorials/getting-started/2_01_toplevel.md @@ -9,6 +9,7 @@ category: "Tooling" An OCaml toplevel is a chat between the user and OCaml. The user writes OCaml code, and UTop evaluates it. This is why it is also called a Read-Eval-Print-Loop (REPL). Several OCaml toplevels exist, like `ocaml` and `utop`. We recommend using UTop, which is part of the [OCaml Platform](/docs/platform) toolchain. To run UTop, we use the `utop` command, which looks like this: + ```shell $ utop ────────┬─────────────────────────────────────────────────────────────┬───────── @@ -30,6 +31,7 @@ Lines ending with double semicolons trigger the parsing, type checking, and eval Code samples beginning with `#` are intended to be copied/pasted into UTop. For instance, consider the following code snippet: + ```ocaml # 2 + 2;; - : int = 4 @@ -43,7 +45,7 @@ Commands beginning with a hash character `#`, such as `#quit` or `#help`, are no You're now ready to hack with UTop! If you hit any issue with the toplevel, don't hesitate to [ask on Discuss](https://discuss.ocaml.org/). -> Note: The double semicolon `;;` is also a valid token in the OCaml syntax outside the toplevel. In OCaml source code, it is a [no-op](https://en.wikipedia.org/wiki/NOP_(code)), i.e., it does not trigger any behaviour, so it is ignored by the compiler. If your intention is to compile or interpret files as scripts, double semicolons can and should be avoided when writing in OCaml. Leaving them does not raise errors, but they are useless. The compiler tolerates them to allow copy-paste from UTop to a file without having to remove them. +> Note: The double semicolon `;;` is also a valid token in the OCaml syntax outside the toplevel. In OCaml source code, it is a [no-op](https://en.wikipedia.org/wiki/NOP_(code)), i.e., it does not trigger any behaviour, so it is ignored by the compiler. If your intention is to compile or interpret files as scripts, double semicolons can and should be avoided when writing in OCaml. Leaving them does not raise errors, but they are useless. The compiler tolerates them to allow copy-paste from UTop to a file without having to remove them. ## Using Packages in UTop @@ -66,6 +68,7 @@ Error: Unbound module Str # Str.quote {|"hello"|};; - : string = "\"hello\"" ``` + **Tip**: UTop knows about the available libraries and completion works. Outside `utop` you can use `ocamlfind list` to display the complete list of libraries. Note that opam package may bundle several libraries and libraries may bundle several modules. ### Using a Pre-Processor Extension (PPX) in UTop diff --git a/data/tutorials/getting-started/2_02_opam_switch.md b/data/tutorials/getting-started/2_02_opam_switch.md index 592e6200c1..f95e683d52 100644 --- a/data/tutorials/getting-started/2_02_opam_switch.md +++ b/data/tutorials/getting-started/2_02_opam_switch.md @@ -6,13 +6,14 @@ description: | category: "Tooling" --- -OCaml's package manager, opam, introduces the concept of a _switch_, which is an isolated OCaml environment. These switches often cause confusion amongst OCaml newcomers, so this document aims to provide a better understanding of opam switches and their usage for managing dependencies and project-specific configurations. +OCaml's package manager, opam, introduces the concept of a _switch_, which is an isolated OCaml environment. These switches often cause confusion amongst OCaml newcomers, so this document aims to provide a better understanding of opam switches and their usage for managing dependencies and project-specific configurations. Opam is designed to manage multiple concurrent installation prefixes called "switches." Similar to Python's `virtualenv`, an opam switch is a tool that creates isolated environments. They are independent of each other and have their own set of installed packages, repositories, and configuration options. Switches also have their own OCaml compiler, libraries, and binaries. This enables you to have multiple compiler versions available at once. ## Listing Switches The command below will display the opam switches that are configured on your system. After completing installation of OCaml, such as outlined in [Installing OCaml](/docs/installing-ocaml), a single switch called `default` will have been created. At that point, listing the switches will only show that switch. + ```shell $ opam switch list # switch compiler description @@ -33,7 +34,7 @@ Next, **activate** your new switch. This will set it as the currently selected s ``` opam switch my_project -``` +``` Replace `my_project` with the name of your new switch. @@ -42,13 +43,14 @@ Replace `my_project` with the name of your new switch. ``` opam switch ``` + If the output is the name of your new switch, you've successfully activated it! Now you can use it for your OCaml projects and install OCaml packages, libraries, and dependencies specific to this switch without affecting other switches or the system-wide OCaml environment. ## Types of Switches ### Global Switches -Global switches are often used for system-wide OCaml installations and are not tied to a particular project or directory. A switch is created and configured at the system level and is typically used to manage OCaml and its ecosystem on a global scale. +Global switches are often used for system-wide OCaml installations and are not tied to a particular project or directory. A switch is created and configured at the system level and is typically used to manage OCaml and its ecosystem on a global scale. When creating an opam switch, it's global by default unless otherwise configured. You can also explicitly select a global switch by using the opam switch command with the `--global` flag. @@ -78,6 +80,4 @@ Most package-related commands in opam operate within the context of a selected s --- -> Learn more details and uses of opam switches in the [opam manual's File Hierarchies page](https://opam.ocaml.org/doc/Manual.html) and its [page dedicated to switches](https://opam.ocaml.org/doc/man/opam-switch.html). - - +> Learn more details and uses of opam switches in the [opam manual's File Hierarchies page](https://opam.ocaml.org/doc/Manual.html) and its [page dedicated to switches](https://opam.ocaml.org/doc/man/opam-switch.html). diff --git a/data/tutorials/getting-started/3_01_ocaml_on_windows.md b/data/tutorials/getting-started/3_01_ocaml_on_windows.md index 659237255c..9823a3582d 100644 --- a/data/tutorials/getting-started/3_01_ocaml_on_windows.md +++ b/data/tutorials/getting-started/3_01_ocaml_on_windows.md @@ -51,10 +51,10 @@ $ opam --version Once opam is installed, run the `opam init` command to set up your opam environment. You will notice that the repository information fetching stage takes a while to -complete. This is normal (for the moment), so we advise our users to get +complete. This is normal (for the moment), so we advise our users to get themselves their favourite hot beverage while it runs. -opam requires a Unix-like environment to function. By default, +opam requires a Unix-like environment to function. By default, opam relies on Cygwin and is also compatible with MSYS2. At *init-time*, opam scans your machine for available Unix environments and @@ -64,10 +64,9 @@ by opam. This cuts down possible interferences from other tools that interact with such environments. Think of it as a sandboxed environment. - Opam's default behavior when initialising is to install a fresh `switch` as well as an OCaml compiler of version `> 4.05`. By default, opam chooses `mingw` as -a C compiler when creating switches, but know that you can choose to install an +a C compiler when creating switches, but know that you can choose to install an alternative instead, like `msvc`, with the following command: ``` @@ -77,13 +76,17 @@ opam install system-msvc After `opam init` completes, run the following command to update your environment: On CMD: + ``` > for /f "tokens=*" %i in ('opam env --switch=default') do @%i ``` + On PowerShell: + ``` > (& opam env --switch=default) -split '\\r?\\n' | ForEach-Object { Invoke-Expression $_ } ``` + Opam will display the shell update command each time it is needed. You can verify your installation with @@ -108,7 +111,7 @@ You should now have a functioning OCaml environment ready for development. If yo ### WSL2 -If you only need to _run_ OCaml programs on a Windows machine, the simplest solution is to use the Windows Subsystem for Linux 2 (WSL2). WSL2 is a feature that allows Linux programs to run directly on Windows. WSL2 is substantially easier and faster to use than WSL1. Microsoft has comprehensive installation steps for [setting up WSL2](https://docs.microsoft.com/en-us/windows/wsl/install-win10). +If you only need to *run* OCaml programs on a Windows machine, the simplest solution is to use the Windows Subsystem for Linux 2 (WSL2). WSL2 is a feature that allows Linux programs to run directly on Windows. WSL2 is substantially easier and faster to use than WSL1. Microsoft has comprehensive installation steps for [setting up WSL2](https://docs.microsoft.com/en-us/windows/wsl/install-win10). After you have installed WSL2 and chosen one Linux distribution (we suggest [Ubuntu LTS](https://apps.microsoft.com/store/detail/ubuntu/9PDXGNCFSCZV?hl=en-us&gl=US)), you can follow the [Installing OCaml: Installation for Linux and macOS](/docs/installing-ocaml) steps. @@ -124,6 +127,7 @@ easier way to get a working Windows environment on your machine. Diskuv OCaml ("DKML") is an OCaml distribution that supports software development in pure OCaml. The distribution is unique because of its: + * full compatibility with OCaml standards like opam, Dune, and OCamlFind. * focus on "native" development (desktop software, mobile apps, and embedded software) through support for the standard native compilers, like Visual Studio and Xcode. @@ -194,7 +198,7 @@ that covers getting WSL2 and Visual Studio Code connected. system using opam: ```console -$ opam install merlin +opam install merlin ``` The installation procedure will print instructions on how to link Merlin with diff --git a/data/tutorials/getting-started/3_02_arm_fix.md b/data/tutorials/getting-started/3_02_arm_fix.md index 15d29bf76c..42b0755407 100644 --- a/data/tutorials/getting-started/3_02_arm_fix.md +++ b/data/tutorials/getting-started/3_02_arm_fix.md @@ -11,17 +11,18 @@ Since [Homebrew has changed](https://github.com/Homebrew/brew/issues/9177) the w Before we get started, let's check where Homebrew is installed. We can do this by running this in the CLI: ```shell -$ where brew +where brew ``` -If the response is `/usr/local/bin/brew`, we'll need to make the changes. It needs to be `/opt/homebrew/bin/brew`. + +If the response is `/usr/local/bin/brew`, we'll need to make the changes. It needs to be `/opt/homebrew/bin/brew`. ### Install CLT -First, ensure the Command Line Tools (CLT) are installed by running +First, ensure the Command Line Tools (CLT) are installed by running ```shell $ ls /Library/Developer/CommandLineTools -Library SDKs usr +Library SDKs usr ``` If they're not installed, let's install them now. You don't have to install all of XCode; you can install just the CLT by [downloading them directly from Apple's Developer](https://developer.apple.com/download/all/). Look for a non-beta version for stability, like "Command Line Tools for XCode 14.3.1" @@ -33,14 +34,14 @@ Next, it's necessary to disable Rosetta if you have it installed. This [Apple Su 1. Uninstall Homebrew by running the following: ```shell -$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh)" -$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)" +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh)" +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)" ``` 2. Reinstall Homebrew: ```Shell -$ brew install /Users/tarides/Library/Caches/Homebrew/downloads/9e6d2a225119ad88cde6474d39696e66e4f87dc4a4d101243b91986843df691e--libev--4.33.arm64_monterey.bottle.tar.gz +brew install /Users/tarides/Library/Caches/Homebrew/downloads/9e6d2a225119ad88cde6474d39696e66e4f87dc4a4d101243b91986843df691e--libev--4.33.arm64_monterey.bottle.tar.gz ``` 3. Check to see if Homebrew is in the correct location now. It should return what's shown below: diff --git a/data/tutorials/getting-started/3_03_ocaml_playground.md b/data/tutorials/getting-started/3_03_ocaml_playground.md index 7f52cc9728..eaeaddb461 100644 --- a/data/tutorials/getting-started/3_03_ocaml_playground.md +++ b/data/tutorials/getting-started/3_03_ocaml_playground.md @@ -7,7 +7,7 @@ description: | category: "Resources" --- -Welcome to OCaml's in-browser playground! +Welcome to OCaml's in-browser playground! The [OCaml Playground](https://ocaml.org/play) is made to make it easier for users, especially beginners, to get started with OCaml without worrying about installing anything. Everything is ready to use once you open it. @@ -38,6 +38,7 @@ Let's start with something simple. Type the following on your editor panel and c ``` 2+3 ``` + You should see the following output. `- : int = 5` @@ -47,6 +48,7 @@ Now, clear the output and also delete the things on the editor panel. Let's try ``` "OCaml is amazing" ``` + You should see the following output. `- : string = "OCaml is amazing"` @@ -72,6 +74,7 @@ let () = let res = fib_par n num_domains in Printf.printf "fib(%d) = %d\n" n res ``` + The output will be the following. ``` @@ -82,6 +85,7 @@ val n : int = 20 val fib : int -> int = val fib_par : int -> int -> int = ``` + ## Autocomplete The playground also supports code completion. It helps users by suggesting and completing their input based on the context. @@ -106,4 +110,4 @@ In contrast, when you separate these expressions with a `;;`, [like this](/play# ## Bottom Line -Congratulations! You have made it to the end. Hopefully, by now, you have a better idea how to use the [OCaml Playground](/play). Use this to practice the OCaml code and have fun. Happy Hacking! \ No newline at end of file +Congratulations! You have made it to the end. Hopefully, by now, you have a better idea how to use the [OCaml Playground](/play). Use this to practice the OCaml code and have fun. Happy Hacking! diff --git a/data/tutorials/guides/0tt_00_formatting_text.md b/data/tutorials/guides/0tt_00_formatting_text.md index ccf6f6404b..083563283d 100644 --- a/data/tutorials/guides/0tt_00_formatting_text.md +++ b/data/tutorials/guides/0tt_00_formatting_text.md @@ -15,6 +15,7 @@ intended to break lines in a nice way (let's say “automatically when it is necessary”). ## Principles + Line breaking is based on three concepts: * **boxes**: a box is a logical pretty-printing unit, which defines a @@ -29,19 +30,20 @@ Line breaking is based on three concepts: * **Indentation rules**: When a line break occurs, the pretty-printing engines fixes the indentation (or amount of leading spaces) of the new line using indentation rules, as follows: - * A box can state the extra indentation of every new line opened + * A box can state the extra indentation of every new line opened in its scope. This extra indentation is named **box breaking indentation**. - * A break hint can also set the additional indentation of the new + * A break hint can also set the additional indentation of the new line it may fire. This extra indentation is named **hint breaking indentation**. - * If break hint `bh` fires a new line within box `b`, then the + * If break hint `bh` fires a new line within box `b`, then the indentation of the new line is simply the sum of: the current indentation of box `b` `+` the additional box breaking indentation, as defined by box `b` `+` the additional hint breaking indentation, as defined by break hint `bh`. ## Boxes + There are 4 types of boxes. (The most often used is the “hov” box type, so skip the rest at first reading). @@ -90,6 +92,7 @@ the value of the break that is explained below): ```text --b--b-- ``` + But "---b---b---" that cannot fit on the line is written ```text @@ -105,12 +108,14 @@ the value of the break that is explained below): ```text --b--b-- ``` + But if "---b---b---" cannot fit on the line, it is written as ```text ---b---b --- ``` + The first break hint does not lead to a new line, since there is enough room on the line. The second one leads to a new line since there is no more room to print the material following it. If the @@ -123,8 +128,8 @@ the value of the break that is explained below): --- ``` - ## Printing Spaces + Break hints are also used to output spaces (if the line is not split when the break is encountered, otherwise the new line indicates properly the separation between printing items). You output a break hint using @@ -153,6 +158,7 @@ For instance, if b is `break 1 0` in the output "--b--b--", we get ```text -- -- -- ``` + or, according to the remaining room on the line: ```text @@ -169,8 +175,8 @@ instead. (For instance `print_space ()` that is a convenient abbreviation for `print_break 1 0` and outputs a single space or break the line.) - ## Indentation of New Lines + The user gets 2 ways to fix the indentation of new lines: * **when defining the box**: when you open a box, you can fix the @@ -183,12 +189,14 @@ The user gets 2 ways to fix the indentation of new lines: ---[--b--b --b-- ``` + with `open_hovbox 2`, we get ```text ---[--b--b --b-- ``` + Note: the `[` sign in the display is not visible on the screen, it is just there to materialise the aperture of the pretty-printing box. Last “screen” stands for: @@ -214,8 +222,8 @@ The user gets 2 ways to fix the indentation of new lines: -- ``` - ## Refinement on “hov” Boxes + ### Packing and Structural “hov” Boxes The “hov” box type is refined into two categories. @@ -231,6 +239,7 @@ The “hov” box type is refined into two categories. to new lines even if there is enough room on the current line. ### Differences Between a Packing and a Structural “hov” Box + The difference between a packing and a structural “hov” box is shown by a routine that closes boxes and parentheses at the end of printing: with packing boxes, the closure of boxes and parentheses do not lead to new @@ -245,6 +254,7 @@ box (open_hovbox), `[(---[(----[(---b)]b)]b)]` is printed as follows: (---- (---))) ``` + If we replace the packing boxes by structural boxes (open_box), each break hint that precedes a closing parenthesis can show the boxes structure, if it leads to a new line; hence `[(---[(----[(---b)]b)]b)]` @@ -277,7 +287,7 @@ When writing a pretty-printing routine, follow these simple rules: definition. You will probably treat the first three spaces as “unbreakable spaces” and write them directly in the string constants for keywords, and print `"let rec "` before the identifier, and - similarly write ` =` to get an unbreakable space after the + similarly write `=` to get an unbreakable space after the identifier; in contrast, the space after the `=` sign is certainly a break hint, since breaking the line after `=` is a usual (and elegant) way to indent the expression part of a definition. In @@ -301,6 +311,7 @@ When writing a pretty-printing routine, follow these simple rules: input.) ## Printing to `stdout`: Using `printf` + The `format` module provides a general printing facility “à la” `printf`. In addition to the usual conversion facility provided by `printf`, you can write pretty-printing indications directly inside the @@ -350,6 +361,7 @@ type lambda = | Var of string | Apply of lambda * lambda ``` + I use the format library to print the lambda-terms: ```ocaml @@ -373,6 +385,7 @@ and print_lambda = function close_box() | e -> print_app e ``` + In Caml Light, replace the first line by: diff --git a/data/tutorials/guides/0tt_02_file_manipulation.md b/data/tutorials/guides/0tt_02_file_manipulation.md index 78605a317c..e667a2e7f0 100644 --- a/data/tutorials/guides/0tt_02_file_manipulation.md +++ b/data/tutorials/guides/0tt_02_file_manipulation.md @@ -14,6 +14,7 @@ Official documentation for the modules of interest: the core library including the initially opened module Stdlib and Printf. ## Buffered Channels + The normal way of opening a file in OCaml returns a **channel**. There are two kinds of channels: @@ -21,6 +22,7 @@ are two kinds of channels: * channels that read from a file: type `in_channel` ### Writing + For writing into a file, you would do this: 1. Open the file to obtain an `out_channel` @@ -36,6 +38,7 @@ Commonly used functions: `open_out`, `open_out_bin`, `flush`, Standard `out_channel`s: `stdout`, `stderr` ### Reading + For reading data from a file you would do this: 1. Open the file to obtain an `in_channel` @@ -52,6 +55,7 @@ Commonly used functions: `open_in`, `open_in_bin`, `close_in`, Standard `in_channel`: `stdin` ### Seeking + Whenever you write or read something to or from a channel, the current position changes to the next character after what you just wrote or read. Occasionally, you may want to skip to a particular position in the @@ -59,6 +63,7 @@ file, or restart reading from the beginning. This is possible for channels that point to regular files, use `seek_in` or `seek_out`. ### Gotchas + * Don't forget to flush your `out_channel`s if you want to actually write something. This is particularly important if you are writing to non-files such as the standard output (`stdout`) or a socket. diff --git a/data/tutorials/guides/0tt_03_calling_c_libraries.md b/data/tutorials/guides/0tt_03_calling_c_libraries.md index 531e9b0f7b..e63629400a 100644 --- a/data/tutorials/guides/0tt_03_calling_c_libraries.md +++ b/data/tutorials/guides/0tt_03_calling_c_libraries.md @@ -7,6 +7,7 @@ category: "Tutorials" --- ## MiniGtk + While the structure of lablgtk outlined in [Introduction to Gtk](https://v2.ocaml.org/learn/tutorials/introduction_to_gtk.html) seems perhaps over-complex, it's worth considering exactly why the author chose two @@ -43,6 +44,7 @@ win#add lbl;; let () = Gtk.main () ``` + I defined a single abstract type to cover all `GtkObject`s (and "subclasses" of this C structure). In the `Gtk` module you'll find this type definition: @@ -82,6 +84,7 @@ gtk_label_new_c (value str) gtk_label_new (String_val (str))))); } ``` + Before explaining this function further, I'm going to take a step back and look at the hierarchy of our Gtk classes. I've chosen to reflect the actual Gtk widget hierarchy as closely as possible. All Gtk widgets are @@ -141,6 +144,7 @@ class virtual widget ?show obj = initializer if show <> Some false then self#show end ``` + This class is considerably more complex. Let's look at the initialization code first: @@ -266,6 +270,7 @@ class label ~text may (gtk_label_set_line_wrap obj) line_wrap end ``` + Although this class is bigger than the ones we've looked at up til now, it's really more of the same idea, *except* that this class isn't virtual. You can create instances of this class which means it finally @@ -280,12 +285,14 @@ class label ~text ... () = inherit misc ... obj end ``` + (Pop quiz: what happens if we need to define a class which is both a base class from which other classes can be derived, and is also a non-virtual class of which the user should be allowed to create instances?) #### Wrapping Calls to C Libraries + Now we'll look in more detail at actually wrapping up calls to C library functions. Here's a simple example: @@ -303,6 +310,7 @@ gtk_label_set_text_c (value obj, value str) CAMLreturn (Val_unit); } ``` + Comparing the OCaml prototype for the external function call (in the comment) with the definition of the function we can see two things: @@ -374,6 +382,7 @@ caml__roots_obj.ntables = 2; caml__roots_obj.tables [0] = &obj; caml__roots_obj.tables [1] = &str; ``` + And for `CAMLreturn (foo)`: ```C diff --git a/data/tutorials/guides/0tt_04_calling_fortran_libraries.md b/data/tutorials/guides/0tt_04_calling_fortran_libraries.md index 25173a1be2..39f2e11cf3 100644 --- a/data/tutorials/guides/0tt_04_calling_fortran_libraries.md +++ b/data/tutorials/guides/0tt_04_calling_fortran_libraries.md @@ -31,6 +31,7 @@ these have been tested with the GNU fortran 90 compiler (gfort) and will not be until it has proven itself through some time. ### Step 1: Compile the Fortran Routine + Where C/C++ have only one category of subroutine (the function), Fortran has two: the function and the subroutine. The function is the equivalent to a non-void C function in that it takes parameters and always returns @@ -65,7 +66,7 @@ Reals are equivalent to C doubles and integers are equivalent to C longs. In addition, Fortran passes everything by reference so the corresponding C prototype for our gtd6 function is -` int gtd6_(integer *iyd, real* sec, real* alt, real* glat, real* glong, real* dens, real* temp);` +`int gtd6_(integer *iyd, real* sec, real* alt, real* glat, real* glong, real* dens, real* temp);` Note that its up to the caller to know that `dens` and `temp` are actually arrays. Failure to pass an array will cause a segmentation @@ -73,6 +74,7 @@ violation since the gtd6_ function is using them as arrays (yet another reason OCaml shines). ### Step 2: Create the C Wrapper + Because OCaml's foreign function interface is C based, it is necessary to create a C wrapper. To avoid difficulties in passing back arrays of values, we are going to simply create a function that will return the @@ -93,6 +95,7 @@ CAMLprim value gtd6_t (value iydV, value secVal, value altVal, value latVal, val CAMLreturn( caml_copy_double( t[1] ) ); } ``` + A few points of interest 1. The file must include the OCaml header files `alloc.h`, `memory.h`, @@ -107,14 +110,15 @@ A few points of interest macro to create a new value containing the return value and to return it respectively. -### Step 3: Compile the Shared Library. +### Step 3: Compile the Shared Library + Now having the two source files funcs.f and wrapper.c we need to create a shared library that can be loaded by OCaml. Its easier to do this as a multistep process, so here are the commands: `prompt> g77 -c funcs.f` -`prompt> cc -I -c wrapper.c ` +`prompt> cc -I -c wrapper.c` `prompt> cc -shared -o wrapper.so wrapper.o funcs.o -lg2c` @@ -124,6 +128,7 @@ required to provide the implementations of the built in fortran functions that are used. ### Step 4: Now to OCaml + Now in an OCaml file (gtd6.ml) we have to define the external reference to the function and a function to call it. @@ -135,6 +140,7 @@ let () = print_double (temp 1 2.0 3.0 4.0 5.0); print_newline () ``` + This tells OCaml that the temp function takes 5 parameters and returns a single floating point and calls the C function gtd6_t. @@ -142,7 +148,8 @@ At this point, the steps that are given are to compile this into bytecode. I don't yet have much experience compiling to native so I'll let some else help out (or wait until I learn how to do it). -``` -prompt> ocamlc -c gtd6.ml prompt> ocamlc -o test gtd6.cmo wrapper.so -``` +`prompt> ocamlc -c gtd6.ml` + +`prompt> ocamlc -o test gtd6.cmo wrapper.so` + And voila, we've called the fortran function from OCaml. diff --git a/data/tutorials/guides/1wf_00_using_the_ocaml_compiler_toolchain.md b/data/tutorials/guides/1wf_00_using_the_ocaml_compiler_toolchain.md index 1ecc55c889..6b544822fb 100644 --- a/data/tutorials/guides/1wf_00_using_the_ocaml_compiler_toolchain.md +++ b/data/tutorials/guides/1wf_00_using_the_ocaml_compiler_toolchain.md @@ -41,9 +41,10 @@ But if you want to try `ocamlc`, you can go ahead and try the following. Create a new directory named `hello` and navigate to the directory: ```shell -$ mkdir hello -$ cd hello +mkdir hello +cd hello ``` + Next, create a file named `hello.ml` and add the following code with your favorite text editor: ```shell @@ -53,12 +54,12 @@ let () = print_endline "Hello OCaml!" Now, we are ready to run the code. Save the file and return to the command line. Let's compile the code: ```dune -$ ocamlc -o hello hello.ml +ocamlc -o hello hello.ml ``` -The `-o hello` option tells the compiler to name the output executable as `hello`. The executable `hello` contains compiled OCaml bytecode. In addition, two other files are produced, `hello.cmi` and `hello.cmo`. +The `-o hello` option tells the compiler to name the output executable as `hello`. The executable `hello` contains compiled OCaml bytecode. In addition, two other files are produced, `hello.cmi` and `hello.cmo`. -`hello.cmi` contains compiled interface information for OCaml modules. An interface file includes type information and module signatures but doesn't contain the actual code. +`hello.cmi` contains compiled interface information for OCaml modules. An interface file includes type information and module signatures but doesn't contain the actual code. `hello.cmo` contains the compiled bytecode for OCaml modules. Bytecode is an intermediate representation of the code that is executed by the OCaml interpreter or runtime system. @@ -70,6 +71,7 @@ Now let's run the executable and see what happens: $ ./hello Hello OCaml! ``` + Voilà! It says, `Hello OCaml!`. We can change the string or add more content, save the file, recompile, and rerun. @@ -215,13 +217,13 @@ structure, build, and run dune projects. ### Bytecode Using Dune -Dune is a build system for OCaml projects, and it allows you to configure different modes for building your executables. We will use `(modes byte exe)` stanza in the `dune` file, which will produce both bytecode (interpreted) and native executable versions of the OCaml program. +Dune is a build system for OCaml projects, and it allows you to configure different modes for building your executables. We will use `(modes byte exe)` stanza in the `dune` file, which will produce both bytecode (interpreted) and native executable versions of the OCaml program. Let's create an example project named `myproject`. ```dune -$ mkdir myproject -$ cd myproject +mkdir myproject +cd myproject ``` Create a `dune-project` file, add the following content. @@ -253,7 +255,7 @@ let () = print_endline "Hello Dune!" Finally, we compile and execute it. ```shell -$ dune build main.bc +dune build main.bc ``` The `.bc` stands for generic bytecode file, and it can be an executable or library. @@ -262,16 +264,18 @@ The `.bc` stands for generic bytecode file, and it can be an executable or libra $ dune exec ./main.bc Hello Dune! ``` + We can also do that with `.exe`. ```shell -$ dune build main.exe +dune build main.exe ``` ```shell $ dune exec ./main.exe Hello Dune! ``` + ## Other Build Systems - [OMake](https://github.com/ocaml-omake/omake) Another OCaml build system. diff --git a/data/tutorials/guides/1wf_01_debugging.md b/data/tutorials/guides/1wf_01_debugging.md index 29de098f72..87ba99cd55 100644 --- a/data/tutorials/guides/1wf_01_debugging.md +++ b/data/tutorials/guides/1wf_01_debugging.md @@ -17,7 +17,6 @@ This tutorial presents four techniques for debugging OCaml programs: OCaml program * [Using Thread Sanitizer to detect a data race](#detecting-a-data-race-with-thread-sanitizer) in an OCaml 5 program - ## Tracing Functions Calls in the Toplevel The simplest way to debug programs in the toplevel is to follow the function @@ -161,13 +160,38 @@ purpose formats are more suited to get the relevant information, than what can be output automatically by the generic pretty-printer used by the trace mechanism. +Compiler builtins help display useful debugging messages. They indicate a location in the program's source. +For example, + +```ocaml +match Message.unpack response with +| Some y -> y +| None -> (Printf.eprintf "Invalid message at %s" __LOC__; raise Invalid_argument) +``` + +At compile time, the `__LOC__` builtin is substituted with its location in the program, described as a string `"File %S, line %d, characters %d-%d"`. File name, line number, start character and end character are also available through the `__POS__` builtin: + +```ocaml +match Message.unpack response with +| Some y -> y +| None -> + let fname, lnum, _cstart, _cend = __POS__ in + Printf.printf "At line %d in file %s, an incorrect response was passed to Message.unpack" + lnum fname; + flush stdout; raise Invalid_argument +``` + +Compiler builtins are described in the +[standard library](https://ocaml.org/manual/5.2/api/Stdlib.html#1_Debugging) documentation. + ## The OCaml Debugger We now give a quick tutorial for the OCaml debugger (`ocamldebug`). Before starting, please note that -- `ocamldebug` runs on `ocamlc` bytecode programs (it does not work on + +* `ocamldebug` runs on `ocamlc` bytecode programs (it does not work on native code executables), and -- it does not work under native Windows ports of OCaml (but it runs +* it does not work under native Windows ports of OCaml (but it runs under the Cygwin port). ### Launching the Debugger @@ -185,6 +209,7 @@ let () = add_address "IRIA" "Rocquencourt";; print_string (find_address "INRIA"); print_newline ();; ``` + ```mdx-error val l : (string * string) list ref = {contents = [("IRIA", "Rocquencourt")]} val find_address : string -> string = @@ -266,7 +291,6 @@ let rec assoc x = function The function that calls it is in module `Uncaught`, file `uncaught.ml` line 8, char 38: - ```ocaml print_string (find_address "INRIA"); print_newline ();; @@ -372,7 +396,6 @@ From this back trace it should be clear that we receive a `Not_found` exception in `List.assoc` from the `Stdlib` when calling `find_address` on line 8. - The environment variable `OCAMLRUNPARAM` also works when working on a program built with `dune`: @@ -383,6 +406,7 @@ program built with `dune`: (modules uncaught) ) ``` + ``` OCAMLRUNPARAM=b dune exec ./uncaught.exe Fatal error: exception Not_found @@ -391,7 +415,6 @@ Called from Dune__exe__Uncaught.find_address in file "uncaught.ml" (inlined), li Called from Dune__exe__Uncaught in file "uncaught.ml", line 8, characters 15-37 ``` - ## Detecting a Data Race with Thread Sanitizer With the introduction of Multicore parallelism in OCaml 5, comes the @@ -403,6 +426,7 @@ report these. To install the TSan mode, create a dedicated TSan switch by running the following command (here we create a 5.2.0 switch): + ``` opam switch create 5.2.0+tsan ocaml-variants.5.2.0+options ocaml-option-tsan ``` @@ -414,11 +438,12 @@ Note: TSan is supported on all architectures with a native code compiler since OCaml 5.2.0. Troubleshooting: -- If the above fails during installation of `conf-unwind` with `No + +* If the above fails during installation of `conf-unwind` with `No package 'libunwind' found`, try setting the environment variable `PKG_CONFIG_PATH` to point to the location of `libunwind.pc`, for example, `PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig` -- If the above fails with an error along the lines of +* If the above fails with an error along the lines of `FATAL: ThreadSanitizer: unexpected memory mapping 0x61a1a94b2000-0x61a1a94ca000`, this is [a known issue with older versions of TSan](https://github.com/google/sanitizers/issues/1716) and can be addressed by reducing ASLR entropy by running @@ -447,6 +472,7 @@ Next, it spawns two parallel `Domain`s `t1` and `t2` that both update the field `v.x`. Here is a corresponding `dune` file: + ```dune (executable (name race) @@ -456,6 +482,7 @@ Here is a corresponding `dune` file: If we compile and run the program using `dune` under a regular `5.2.0` switch the program appears to work: + ``` $ opam exec -- dune build ./race.exe $ opam exec -- dune exec ./race.exe @@ -464,6 +491,7 @@ v.x is 11 However, if we compile and run the program with Dune from the new `5.2.0+tsan` switch TSan warns us of a data race: + ``` $ opam switch 5.2.0+tsan $ opam exec -- dune build ./race.exe @@ -500,9 +528,10 @@ this required no change to our `dune` file. The TSan report warns of a data race between two uncoordinated writes happening in parallel and prints a back trace for both: -- The first back trace reports a write at `race.ml` in line + +* The first back trace reports a write at `race.ml` in line 6 of `thread T4` and -- the second back trace reports a previous write at +* the second back trace reports a previous write at `race.ml` in line 5 of `thread T1` Looking again at our program, we realize that these two writes are in @@ -524,6 +553,7 @@ let () = If we recompile and run our program with this change, it now completes without TSan warnings: + ``` $ opam exec -- dune build ./race.exe $ opam exec -- dune exec ./race.exe @@ -534,6 +564,7 @@ The TSan instrumentation benefits from compiling programs with debug information, which happens by default under `dune`. To manually invoke the `ocamlopt` compiler under our `5.2.0+tsan` switch it is thus suffient to pass it the `-g` flag: + ``` -$ ocamlopt -g -o race.exe -I +unix unix.cmxa race.ml +ocamlopt -g -o race.exe -I +unix unix.cmxa race.ml ``` diff --git a/data/tutorials/guides/1wf_02_error_handling.md b/data/tutorials/guides/1wf_02_error_handling.md index 1b031824a7..3b6ee3e833 100644 --- a/data/tutorials/guides/1wf_02_error_handling.md +++ b/data/tutorials/guides/1wf_02_error_handling.md @@ -34,6 +34,7 @@ errors aren't ignored. This has been the cause of many bugs, some with dire consequences. This is not the proper way to deal with errors in OCaml. There are three major ways to make it impossible to ignore errors in OCaml: + 1. Exceptions 1. **`option`** values 1. **`result`** values @@ -101,6 +102,7 @@ Stack overflow during evaluation (looping recursion?). ``` Although the last one doesn't look as an exception, it actually is. + ```ocaml # try loop 42 with Stack_overflow -> [];; - : int list = [] @@ -117,6 +119,7 @@ are intended to be raised by user-written functions: Functions are provided by the standard library to raise `Invalid_argument` and `Failure` using a string parameter: + ```ocaml val invalid_arg : string -> 'a (** @raise Invalid_argument *) @@ -126,6 +129,7 @@ val failwith : string -> 'a When implementing a software component which exposes functions raising exceptions, a design decision must be made: + * Use the preexisting exceptions * Raise custom exceptions @@ -140,9 +144,11 @@ desirable for errors that must be handled at the client level. Because handling exceptions interrupts normal control flow, using them can complicate some tasks requiring strictly ordered and coupled processes. For these scenarios, the `Fun` module of the standard library provides: + ```ocaml val protect : finally:(unit -> unit) -> (unit -> 'a) -> 'a ``` + This function is meant to be used when something _always_ needs to be done _after_ a computation is complete, whether it succeeds or fails. The unlabeled function argument is called first, then the function passed as the @@ -179,6 +185,7 @@ val head_channel : in_channel -> int -> string list = Fun.protect ~finally work;; val head_file : string -> int -> string list = ``` + When `head_file` is called, it opens a file descriptor, defines `finally` and `work`, then `Fun.protect ~finally work` performs two computations in order: `work ()` and then `finally ()`, and has the same result as `work ()`, either @@ -188,7 +195,7 @@ closed after use. ### Asynchronous Exceptions Some exceptions don't arise because something attempted by the program failed, -but rather because an external factor is impeding its execution. Those +but rather because an external factor is impeding its execution. Those exceptions are called asynchronous. These include: * `Out_of_memory` @@ -301,6 +308,7 @@ Segmentation fault (core dumped) ### Language Bugs When a crash isn't coming from: + * A limitation of the native code compiler * An inherently unsafe function such as are found in modules `Marshal` and `Obj` @@ -312,12 +320,13 @@ it may be a language bug. It happens. Here is what to do when this is suspected: 1. File an issue in the [OCaml Bug Tracker in GitHub](https://github.com/ocaml/ocaml/issues) -Here is an example of such a bug: https://github.com/ocaml/ocaml/issues/7241 +Here is an example of such a bug: ### Safe vs. Unsafe Functions Uncaught exceptions cause runtime crashes. Therefore, there is a tendency to use the following terminology: + * Function raising exceptions: Unsafe * Function handling errors in data: Safe @@ -335,6 +344,7 @@ is of type `int option` - or the absence of data due to any error as `None`. Using **`option`** it is possible to write functions that return `None` instead of throwing an exception. Here are two examples of such functions: + ```ocaml # let div_opt m n = try Some (m / n) with @@ -346,6 +356,7 @@ val div_opt : int -> int -> int option = Not_found -> None;; val find_opt : ('a -> bool) -> 'a list -> 'a option = ``` + We can try those functions: ```ocaml @@ -375,17 +386,20 @@ behavior where one may raise an exception and the other returns an option. In the above examples, the convention of the standard library is used: adding an `_opt` suffix to the name of the version of the function that returns an option instead of raising an exception. + ```ocaml val find: ('a -> bool) -> 'a list -> 'a (** @raise Not_found *) val find_opt: ('a -> bool) -> 'a list -> 'a option ``` + This is extracted from the `List` module of the standard library. However, some projects tend to avoid or reduce the usage of exceptions. In such a context, the opposite convention is relatively common: the version of the function that raises exceptions is suffixed with `_exn`. Using the same functions, that would give the specification: + ```ocaml val find_exn: ('a -> bool) -> 'a list -> 'a (** @raise Not_found *) @@ -410,17 +424,20 @@ Error: This expression has type 'a option In order to combine option values with other values, conversion functions are needed. Here are the functions provided by the **`option`** module to extract the data contained in an option: + ```ocaml val get : 'a t -> 'a val value : 'a t -> default:'a -> 'a val fold : none:'a -> some:('b -> 'a) -> 'b t -> 'a ``` + `get` returns the contents, or raises `Invalid_argument` if applied to `None`. `value` returns the contents, or its `default` argument if applied to `None`. `fold` returns its `some` argument applied to the contents of the option, or its `none` argument if applied to `None`. As a remark, observe that `value` can be implemented using `fold`: + ```ocaml # let value ~default = Option.fold ~none:default ~some:Fun.id;; val value : default:'a -> 'a option -> 'a = @@ -431,11 +448,13 @@ val value : default:'a -> 'a option -> 'a = ``` It is also possible to perform pattern matching on option values: + ```ocaml match opt with | None -> ... (* Something *) | Some x -> ... (* Something else *) ``` + However, sequencing such expressions leads to deep nesting which is often considered bad: @@ -458,6 +477,7 @@ provided as a string. For instance, given the string example). Here is a questionable but straightforward implementation using exceptions: + ```ocaml # let host email = let fqdn_pos = String.index email '@' + 1 in @@ -470,6 +490,7 @@ Here is a questionable but straightforward implementation using exceptions: if fqdn <> "" then fqdn else raise Not_found;; val host : string -> string = ``` + This may fail by raising `Not_found` if the first the call to `String.index` does, which could happen if there is no `@` character in the input string, signifying that it's not an email address. However, if the second call to @@ -525,6 +546,7 @@ If there isn't anything to supply to `f`, `None` is forwarded. If we don't take arguments order into account, `Option.bind` is almost exactly the same, except we assume `f` returns an option. Therefore, there is no need to rewrap its result, since it's already an option value: + ```ocaml let bind opt f = match opt with | Some x -> f x @@ -534,12 +556,14 @@ let bind opt f = match opt with `bind` having flipped parameter order with respect to `map` allows its use as a [binding operator](/manual/bindingops.html), which is a popular extension of OCaml providing means to create “custom `let`”. Here is how it goes: + ```ocaml # let ( let* ) = Option.bind;; val ( let* ) : 'a option -> ('a -> 'b option) -> 'b option = ``` Using these mechanisms, here is a possible way to rewrite `host_opt`: + ```ocaml # let host_opt email = let* fqdn_pos = Option.map (( + ) 1) (String.index_opt email '@') in @@ -554,15 +578,16 @@ val host_opt : string -> string option = This version was picked to illustrate how to use and combine operations on options allowing users to achieve some balance between understandability and robustness. A couple of observations: + * As in the original `host` function (with exceptions): - - The calls to `String` functions (`index_opt`, `length`, and `sub`) are the + * The calls to `String` functions (`index_opt`, `length`, and `sub`) are the same and in the same order - - The same local names are used with the same types + * The same local names are used with the same types * There isn't any remaining indentation or pattern-matching * Line 1: - - right-hand side of `=` : `Option.map` allows adding 1 to the result of + * right-hand side of `=` : `Option.map` allows adding 1 to the result of `String.index_opt`, if it didn't fail - - left-hand side of `=` : the `let*` syntax turns all the rest of the code + * left-hand side of `=` : the `let*` syntax turns all the rest of the code (from line 2 to the end) into the body of an anonymous function which takes `fqdn_pos` as parameter, and the function `( let* )` is called with `fqdn_pos` and that anonymous function. @@ -612,10 +637,13 @@ constructor. Nevertheless, `Result.map` is implemented similarly: on `Error`, it also behaves like identity. Here is its type: + ```ocaml val map : ('a -> 'b) -> ('a, 'c) result -> ('b, 'c) result ``` + And here is how it is written: + ```ocaml let map f = function | Ok x -> Ok (f x) @@ -626,19 +654,23 @@ The **`result`** module has two map functions: the one we've just seen and anoth one, with the same logic, applied to `Error` Here is its type: + ```ocaml val map_error : ('c -> 'd) -> ('a, 'c) result -> ('a, 'd) result ``` + And here is how it is written: + ```ocaml let map_error f = function | Ok x -> Ok x -| Error e -> f e +| Error e -> Error (f e) ``` The same reasoning applies to `Result.bind`, except there's no `bind_error`. Using those functions, here is an hypothetical example of code using [Anil Madhavapeddy's OCaml YAML library](https://github.com/avsm/ocaml-yaml): + ```ocaml let file_opt = File.read_opt path in let file_res = Option.to_result ~none:(`Msg "File not found") file_opt in begin @@ -650,6 +682,7 @@ end |> Result.map_error (Printf.sprintf "%s, error: %s: " path) ``` Here are the types of the involved functions: + ```ocaml val File.read_opt : string -> string option val Yaml.of_string : string -> (Yaml.value, [`Msg of string]) result @@ -657,13 +690,13 @@ val Yaml.Util.find : string -> Yaml.value -> (Yaml.value option, [`Msg of string val Option.to_result : none:'e -> 'a option -> ('a, 'e) result ``` -- `File.read_opt` is supposed to open a file, read its contents and return it as +* `File.read_opt` is supposed to open a file, read its contents and return it as a string wrapped in an option, if anything goes wrong `None` is returned. -- `Yaml.of_string` parses a string and turns it into an ad hoc OCaml type -- `Yaml.find` recursively searches for a key in a Yaml tree. If found, it returns +* `Yaml.of_string` parses a string and turns it into an ad hoc OCaml type +* `Yaml.find` recursively searches for a key in a Yaml tree. If found, it returns the corresponding data, wrapped in an option -- `Option.to_result` performs conversion of an **`option`** into a **`result`**. -- Finally, `let*` stands for `Result.bind`. +* `Option.to_result` performs conversion of an **`option`** into a **`result`**. +* Finally, `let*` stands for `Result.bind`. Since both functions from the `Yaml` module return **`result`** data, it is easier to write a pipe which processes that type all along. That's why @@ -677,14 +710,17 @@ into an `Error` and `Result.map_error` will never turn an `Error` into an `Ok`. On the other hand, functions passed to `Result.bind` are allowed to fail. As stated before there isn't a `Result.bind_error`. One way to make sense out of that absence is to consider its type, it would have to be: + ```ocaml val Result.bind_error : ('a, 'e) result -> ('e -> ('a, 'f) result) -> ('a, 'f) result ``` + We would have: + * `Result.map_error f (Ok x) = Ok x` * And either: - - `Result.map_error f (Error e) = Ok y` - - `Result.map_error f (Error e) = Error e'` + * `Result.map_error f (Error e) = Ok y` + * `Result.map_error f (Error e) = Error e'` This means an error would be turned back into valid data or changed into another error. This is almost like recovering from an error. However, when @@ -698,11 +734,12 @@ val recover : ('e -> 'a option) -> ('a, 'e) result -> ('a, 'e) result = Although any kind of data can be wrapped as a **`result`** `Error`, it is recommended to use that constructor to carry actual errors, for instance: -- `exn`, in which case the result type just makes exceptions explicit -- `string`, where the error case is a message that indicates what failed -- `string Lazy.t`, a more elaborate form of error message that is only evaluated + +* `exn`, in which case the result type just makes exceptions explicit +* `string`, where the error case is a message that indicates what failed +* `string Lazy.t`, a more elaborate form of error message that is only evaluated if printing is required -- some polymorphic variant, with one case per possible error. This is very +* some polymorphic variant, with one case per possible error. This is very accurate (each error can be dealt with explicitly and occurs in the type), but the use of polymorphic variants sometimes make the code harder to read. @@ -737,9 +774,11 @@ source code are functionally identical: ```ocaml bind a (fun x -> b) ``` + ```ocaml let* x = a in b ``` + ```ocaml a >>= fun x -> b ``` @@ -750,14 +789,17 @@ calls to `bind` are chained. The following three are also equivalent: ```ocaml bind a (fun x -> bind b (fun y -> c)) ``` + ```ocaml let* x = a in let* y = b in c ``` + ```ocaml a >>= fun x -> b >>= fun y -> c ``` + Variables `x` and `y` may appear in `c` in the three cases. The first form isn't very convenient, as it uses a lot of parentheses. The second one is often preferred due to its resemblance with regular local definitions. The third @@ -765,15 +807,19 @@ one is harder to read, as `>>=` associates to the right in order to avoid parentheses in that precise case, but it's easy to get lost. Nevertheless, it has some appeal when named functions are used. It looks a bit like good old Unix pipes: + ```ocaml a >>= f >>= g ``` + looks better than: + ```ocaml let* x = a in let* y = f x in g y ``` + Writing `x >>= f` is very close to what is found in functionally tainted programming languages which have methods and receivers such as Kotlin, Scala, Go, Rust, Swift, or even modern Java, where it would look like: @@ -781,6 +827,7 @@ Go, Rust, Swift, or even modern Java, where it would look like: Here is the same code as presented at the end of the previous section, rewritten using `Result.bind` as a binary opeator: + ```ocaml File.read_opt path |> Option.to_result ~none:(`Msg "File not found") @@ -806,13 +853,15 @@ Guidelines](/docs/guidelines) for more details on those matters. This is done by using the following functions: -- From **`option`** to `Invalid_argument` exception, use function `Option.get`: +* From **`option`** to `Invalid_argument` exception, use function `Option.get`: + ```ocaml val get : 'a option -> 'a ``` -- From **`result`** to `Invalid_argument` exception, use functions +* From **`result`** to `Invalid_argument` exception, use functions `Result.get_ok` and `Result.get_error`: + ```ocaml val get_ok : ('a, 'e) result -> 'a val get_error : ('a, 'e) result -> 'e @@ -824,11 +873,14 @@ To raise other exceptions, pattern matching and `raise` must be used. This is done by using the following functions: -- From **`option`** to **`result`**, use function `Option.to_result`: +* From **`option`** to **`result`**, use function `Option.to_result`: + ```ocaml val to_result : none:'e -> 'a option -> ('a, 'e) result ``` -- From **`result`** to **`option`**, use function `Result.to_option`: + +* From **`result`** to **`option`**, use function `Result.to_option`: + ```ocaml val to_option : ('a, 'e) result -> 'a option ``` @@ -848,6 +900,7 @@ It would be same for **`result`**, except some data must be provided to the `Error` constructor. Some may like to turn this into a higher-order generic function: + ```ocaml # let catch f x = try Some (f x) with _ -> None;; val catch : ('a -> 'b) -> 'a -> 'b option = @@ -893,9 +946,11 @@ match Sys.os_type with It is right to use `failwith`, other operating systems aren't supported, but they are possible. Here is the dual example: + ```ocaml function x when true -> () | _ -> assert false ``` + Here, it wouldn't be correct to use `failwith` because it requires a corrupted system or the compiler to be bugged for the second code path to be executed. Breakage of the language semantics qualifies as extraordinary circumstances. It @@ -917,12 +972,12 @@ fine, so it's a balance. # External Resources -- [“Exceptions”](/manual/coreexamples.html#s%3Aexceptions) in ”The OCaml Manual, The Core Language”, chapter 1, section 6, December 2022 -- [Module **`option`**](/manual/api/Option.html) in OCaml Library -- [Module **`result`**](/manual/api/Result.html) in Ocaml Library -- [“Error Handling”](https://dev.realworldocaml.org/error-handling.html) in “Real World OCaml”, part 7, Yaron Minsky and Anil Madhavapeddy, 2ⁿᵈ edition, Cambridge University Press, October 2022 -- “Add "finally" function to Pervasives”, Marcello Seri, GitHub PR, [ocaml/ocaml/pull/1855](https://github.com/ocaml/ocaml/pull/1855) -- “A guide to recover from interrupts”, Guillaume Munch-Maccagnoni, parf the [`memprof-limits`](https://gitlab.com/gadmm/memprof-limits/) documentation +* [“Exceptions”](/manual/coreexamples.html#s%3Aexceptions) in ”The OCaml Manual, The Core Language”, chapter 1, section 6, December 2022 +* [Module **`option`**](/manual/api/Option.html) in OCaml Library +* [Module **`result`**](/manual/api/Result.html) in Ocaml Library +* [“Error Handling”](https://dev.realworldocaml.org/error-handling.html) in “Real World OCaml”, part 7, Yaron Minsky and Anil Madhavapeddy, 2ⁿᵈ edition, Cambridge University Press, October 2022 +* “Add "finally" function to Pervasives”, Marcello Seri, GitHub PR, [ocaml/ocaml/pull/1855](https://github.com/ocaml/ocaml/pull/1855) +* “A guide to recover from interrupts”, Guillaume Munch-Maccagnoni, parf the [`memprof-limits`](https://gitlab.com/gadmm/memprof-limits/) documentation ``` -$ ocamlcp -p a graphics.cma graphtest.ml -o graphtest -$ ./graphtest -$ ocamlprof graphtest.ml +ocamlcp -p a graphics.cma graphtest.ml -o graphtest +./graphtest +ocamlprof graphtest.ml ``` The comments `(* nnn *)` are added by `ocamlprof`, showing how many @@ -870,7 +902,7 @@ Each sample counts as 0.01 seconds. ### Using `perf` on Linux -Assuming `perf `is installed and your program is compiled into +Assuming `perf`is installed and your program is compiled into native code with `-g` (or ocamlbuild tag `debug`), you just need to type @@ -892,7 +924,7 @@ macOS ships with a performance monitoring and debugging application called `Instruments` that comes with a CPU counter, a Time Profiler, and a System Trace templates. -Once you launch it and select the template you want, you must start _recording_ +Once you launch it and select the template you want, you must start *recording* before you launch your application. As you launch your application, real-time results will appear listed in @@ -904,6 +936,7 @@ From there, you can click on your program there and dig to see which functions a taking the longest to execute. ## Summary + In summary here are some tips for getting the best performance out of your programs: @@ -922,6 +955,7 @@ your programs: optimization will help you. ### Further Reading + You can find out more about how OCaml represents different types by reading the ("Interfacing C with OCaml") chapter in the OCaml manual and also looking at the `mlvalues.h` header file. diff --git a/data/tutorials/guides/1wf_04_multicore_ready.md b/data/tutorials/guides/1wf_04_multicore_ready.md index d03c0ebe9a..9f461b3fb9 100644 --- a/data/tutorials/guides/1wf_04_multicore_ready.md +++ b/data/tutorials/guides/1wf_04_multicore_ready.md @@ -67,7 +67,6 @@ let iter_accounts t f = (* inspect the bank accounts *) Array.iteri (fun account balance -> f ~account ~balance) t; ``` - ## A Proposed Workflow Now if we want to see if this code is Multicore ready for OCaml 5.x, @@ -79,16 +78,15 @@ we can utilise the following workflow: 3. If TSan complains about data races, address the reported issue and go to step 2. - ## Following the Workflow We will now go through the proposed workflow for our example application. - ### Install the Instrumenting TSan Compiler (Step 0) TSan is included in OCaml starting from OCaml 5.2, but has to be explicitly enabled. You can install a TSan switch as follows (here we create a 5.2.0 switch named `5.2.0+tsan`): + ``` shell opam switch create 5.2.0+tsan ocaml-variants.5.2.0+options ocaml-option-tsan ``` @@ -104,6 +102,7 @@ example, `PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig` For a start, we can test our library under parallel usage by running two `Domain`s in parallel. Here's a quick little test runner in `bank_test.ml` utilising this idea: + ``` ocaml let num_accounts = 7 @@ -136,6 +135,7 @@ let _ = The runner creates a bank with 7 accounts containing $100 each and then runs two loops in parallel with: + - One transfering money with `money_shuffle` - Another one repeatedly printing the account balances with `print_balances`: @@ -160,7 +160,6 @@ From the above run under a regular `5.1.0` compiler, one may get the impression that everything is OK, as the balances sum to a total of $700 as expected, indicating that no money is lost. - ### Run the Parallel Tests Under TSan (Step 2) Let us now perform the same test run under TSan. Doing so is as simple @@ -206,13 +205,13 @@ WARNING: ThreadSanitizer: data race (pid=26148) ``` Notice we obtain a back trace of the two racing accesses, with + - A write in one `Domain` coming from the array assignment in - `Bank.transfer` + `Bank.transfer` - A read in another `Domain` coming from a call to `Stdlib.Array.iteri` to read and print the array entries in `print_balances`. - ### Address the Reported Races and Rerun the Tests (Steps 3 and 2) One way to address the reported races is to add a `Mutex`, ensuring @@ -257,7 +256,6 @@ Fatal error: exception Sys_error("Mutex.lock: Resource deadlock avoided") How come we may hit a resource deadlock error when adding just two pairs of `Mutex.lock` and `Mutex.unlock` calls? - ### Address the Reported Races and Rerun the Tests, Take 2 (Steps 3 and 2) Oh, wait! When raising an exception in `transfer`, we forgot to unlock @@ -279,6 +277,7 @@ let transfer t ~src_acc ~dst_acc ~amount = ``` We can now rerun our tests under TSan to confirm the fix: + ``` shell $ opam exec -- dune runtest 0 100 1 100 2 100 3 100 4 100 5 100 6 100 total = 700 @@ -298,16 +297,18 @@ $ opam exec -- dune runtest This works well and TSan no longer complains, so our little library is ready for OCaml 5.x parallelism, hurrah! - ### Final Remarks and a Word of Warning The programming pattern of 'always-having-to-do-something-at-the-end' that we encountered with the missing `Mutex.unlock` is a recurring one for which OCaml offers a dedicate function: + ```ocaml Fun.protect : finally:(unit -> unit) -> (unit -> 'a) -> 'a ``` + Using `Fun.protect`, we could have written our final fix as follows: + ```ocaml let transfer t ~src_acc ~dst_acc ~amount = begin diff --git a/data/tutorials/guides/1wf_05_garbage_collection.md b/data/tutorials/guides/1wf_05_garbage_collection.md index 2dfdfac0f2..1e94ddc230 100644 --- a/data/tutorials/guides/1wf_05_garbage_collection.md +++ b/data/tutorials/guides/1wf_05_garbage_collection.md @@ -11,6 +11,7 @@ In this tutorial, we look at how to use the `Gc` module and how to write your ow At the end of the tutorial, we give some exercises you might try in order to develop a better understanding. ## The `Gc` Module + The `Gc` module contains some useful functions for querying and calling the garbage collector from OCaml programs. @@ -85,6 +86,7 @@ but it should be mostly obvious what it does). The above code causes the GC to print a message at the start of every major collection. ## Finalisation and the Weak Module + We can write a function called a **finaliser** which is called when an object is about to be freed by the GC. @@ -156,7 +158,6 @@ the in-memory copy is written back out to the file, the program must release the lock. Here is some code to define the on-disk format and some low-level functions to read, write, lock, and unlock records: - ```ocaml (* In-memory format. *) @@ -199,7 +200,6 @@ let new_record () = { name = String.make name_size ' '; address = String.make addr_size ' ' } ``` - Because this is a really simple program, we're going to fix the number of records in advance: @@ -231,7 +231,6 @@ from the cache. If the cache gives us `Some record`, then we just return `record` (this promotes the weak pointer to the record to a normal pointer). - ```ocaml (* The finaliser function. *) @@ -263,17 +262,17 @@ records. But it doesn't necessarily mean that the GC *will* collect the records straightaway. In fact it's not likely that it will, so to force the GC to collect the records immediately, we also invoke a major cycle. - Finally, we have some test code. I won't reproduce the test code here, but you can download the complete program and test code [objcache.ml](/media/tutorials/objcache.ml) and compile it with: ```sh -$ ocamlc unix.cma objcache.ml -o objcache +ocamlc unix.cma objcache.ml -o objcache ``` ## Exercises + Here are some ways to extend the example above, in approximately increasing order of difficulty: diff --git a/data/tutorials/guides/rs_00_guidelines.md b/data/tutorials/guides/rs_00_guidelines.md index 6be67ab76d..a6057d404f 100644 --- a/data/tutorials/guides/rs_00_guidelines.md +++ b/data/tutorials/guides/rs_00_guidelines.md @@ -20,7 +20,9 @@ manually, there are some formatting guidelines at the end of this article. ## General Guidelines -### Be Simple and Readable + +### Be Simple and Readable + The time you spend typing the programs is negligible compared to the time spent reading them. That's the reason why you save a lot of time if you work hard to optimise readability. @@ -36,8 +38,8 @@ debugging). > modifications in mind, and never jeopardize readability. > +### Naming Complex Arguments -### Naming Complex Arguments In place of @@ -50,6 +52,7 @@ let temp = expression” in ... ``` + write @@ -64,7 +67,9 @@ let temp = f x y z t u in ... ``` -### Naming Anonymous Functions + +### Naming Anonymous Functions + In the case of an iterator whose argument is a complex function, define the function by a `let` binding as well. In place of @@ -77,6 +82,7 @@ List.map blabla) l ``` + write @@ -93,26 +99,31 @@ List.map f l > ## Programming Guidelines -### How to Program + +### How to Program > > *Always put your handiwork back on the bench,
-> then polish it and repolish it.* +> then polish it and repolish it.* > -#### Write Simple and Clear Programs +#### Write Simple and Clear Programs + Reread, simplify, and clarify at every stage of creation. Use your head! -#### Subdivide Your Programs Into Little Functions +#### Subdivide Your Programs Into Little Functions + Small functions are easier to master. -#### Factor out snippets of repeated code by defining them in separate functions +#### Factor out snippets of repeated code by defining them in separate functions + Sharing code obtained in this way facilitates maintenance, since every correction or improvement automatically spreads throughout the program. Besides, the simple act of isolating and naming a snippet of code sometimes lets you identify an unsuspected feature. -#### Never copy-paste code when programming +#### Never copy-paste code when programming + Pasting code almost surely indicates introducing a code sharing default and neglecting to identify and write a useful auxiliary function. Hence, it means that some code sharing is lost in the program. @@ -130,7 +141,7 @@ more difficult to understand. In conclusion, copy-pasting code leads to programs that are more difficult to read and more difficult to maintain. It must be banished. -### How to Comment Programs +### How to Comment Programs Don't hesitate to comment when there's a difficulty. If there's no difficulty, there's no point in commenting. It merely creates unnecessary noise. @@ -140,7 +151,8 @@ Prefer one comment at the beginning of the function that explains how a particular algorithm works. Once more, if there is no difficulty, there is no point in commenting. -#### Avoid Nocuous Comments +#### Avoid Nocuous Comments + A *nocuous* comment is a comment that does not add any value, e.g., trivial information. The nocuous comment is evidently not of interest; it is a nuisance that uselessly distracts the reader. It @@ -173,13 +185,16 @@ let rec print_lambda lam = | App (l1, l2) -> printf "(%a %a)" print_lambda l1 print_lambda l2 ``` -#### Usage in Module Interface + +#### Usage in Module Interface + The function's usage must appear in the module's interface that exports it, not in the program that implements it. Choose comments as in the OCaml system's interface modules, which will subsequently automatically extract the documentation of the interface module if necessary. -#### Use Assertions +#### Use Assertions + Use assertions as much as possible, as they let you avoid verbose comments while allowing a useful verification upon execution. @@ -192,13 +207,15 @@ let f x = assert (x >= 0); ... ``` + Note as well that an assertion is often preferable to a comment because it's more trustworthy. An assertion is forced to be pertinent because it is verified upon each execution, while a comment can quickly become obsolete, making it detrimental to understanding the program. -#### Comments line by line in imperative code +#### Comments line by line in imperative code + When writing difficult code, and particularly in case of highly imperative code with a lot of memory modifications (physical mutations in data structures), it is sometimes mandatory to comment inside the body @@ -207,18 +224,21 @@ here or to follow successive invariant modifications that the function must maintain. Once more, if there is some difficulty commenting is mandatory, for each program line if necessary. -### How to Choose Identifiers +### How to Choose Identifiers + It's hard to choose identifiers whose name evokes the meaning of the corresponding portion of the program. This is why you must devote particular care to this, emphasising clarity and regularity of nomenclature. -#### Don't use abbreviations for global names +#### Don't use abbreviations for global names + Global identifiers (including the names of functions) can be long because it's important to understand what purpose they serve far from their definition. -#### Separate words by underscores: (`int_of_string`, not `intOfString`) +#### Separate words by underscores: (`int_of_string`, not `intOfString`) + Case modifications are meaningful in OCaml. In effect, capitalised words are reserved for constructors and module names. In contrast, regular variables (functions or identifiers) must start with a lowercase @@ -227,12 +247,14 @@ separation in identifiers. The first word starts the identifier, hence it must be lowercase, and it is forbidden to choose `IntOfString` as a function name. -#### Always give the same name to function arguments which have the same meaning +#### Always give the same name to function arguments which have the same meaning + If necessary, make this nomenclature explicit in a comment at the top of the file. If there are several arguments with the same meaning, then attach numeral suffixes to them. -#### Local identifiers can be brief and should be reused from one function to another +#### Local identifiers can be brief and should be reused from one function to another + This augments style consistency. Avoid using identifiers whose appearance can lead to confusion, such as `l` or `O`, which are easy to confuse with `1` and `0`. @@ -244,14 +266,17 @@ Example: let add_expression expr1 expr2 = ... let print_expression expr = ... ``` + A tolerated exception to the recommendation not to use capitalisation to separate words within identifiers when interfacing with existing libraries which use this naming convention. This lets OCaml library users to orient themselves in the original library documentation more easily. -### How to Use Modules -#### Subdividing into modules +### How to Use Modules + +#### Subdividing into modules + You must subdivide your programs into coherent modules. For each module, you must explicitly write an interface. @@ -259,7 +284,8 @@ For each module, you must explicitly write an interface. For each interface, you must document the things defined by the module: functions, types, exceptions, etc. -#### Opening modules +#### Opening modules + Avoid `open` directives, using instead the qualified identifier notation. Thus you will prefer short but meaningful module names. @@ -277,7 +303,9 @@ let lim = Array.length v - 1 in ... List.map succ ... ... Array.map succ ... ``` -#### When to use open modules rather than leaving them closed + +#### When to use open modules rather than leaving them closed + Consider it normal to open a module that modifies the environment and brings other versions of an important set of functions. For example, the `Format` module automatically provides indented @@ -296,6 +324,7 @@ instance: let f () = Format.print_string "Hello World!"; print_newline () ``` + is bogus since it does not call `Format.print_newline` to flush the pretty-printer queue and output `"Hello World!"`. Instead `"Hello World!"` is stuck into the pretty-printer queue, while @@ -329,7 +358,7 @@ these definitions into one or more module(s) without implementations (containing only types). Then it's acceptable to systematically open the module that exports the shared type definitions. -### Pattern-Matching +### Pattern-Matching Never be afraid of overusing pattern-matching! On the other hand, be careful to avoid nonexhaustive pattern-matching constructs. Complete them with care, @@ -337,22 +366,24 @@ without using a “catch-all” clause such as `| _ -> ...` or `| x -> ...` when it's unnecessary (for example when matching a concrete type defined within the program). See also the next section: compiler warnings. -### Compiler Warnings +### Compiler Warnings + Compiler warnings are meant to prevent potential errors, which is why you absolutely must heed them and correct your programs if compiling them produces such warnings. Besides, programs whose compilation produces warnings have an odor of amateurism which certainly doesn't suit your own work! -#### Pattern-matching warnings +#### Pattern-matching warnings + Warnings about pattern-matching must be treated with the upmost care. * Those with useless clauses should be eliminated, of course. * For nonexhaustive pattern-matching, you must complete the corresponding pattern-matching construct without adding a default - case “catch-all”, such as `| _ -> ... `, but rather with an explicit + case “catch-all”, such as `| _ -> ...`, but rather with an explicit constructor list not examined by the rest of the construct, - e.g., `| Cn _ | Cn1 _ -> ... `. + e.g., `| Cn _ | Cn1 _ -> ...`. > > **Justification**: It's not really more complicated to write @@ -366,12 +397,12 @@ Warnings about pattern-matching must be treated with the upmost care. > handled by the default case. > - * Nonexhaustive pattern-matches induced by clauses with guards must also be corrected. A typical case consists in suppressing a redundant guard. -#### Destructuring `let` bindings +#### Destructuring `let` bindings + A “destructuring `let` binding” is one which binds several names to several expressions simultaneously. You pack all the names you want bound into a collection such as a tuple or a list, @@ -392,7 +423,8 @@ can use it with more complex or simpler patterns. For instance: `let _ = ...` does not define anything, it just evaluate the expression on the right hand side of the `=` symbol. -#### The destructuring `let` must be exhaustive +#### The destructuring `let` must be exhaustive + Only use destructuring `let` bindings when the pattern-matching is exhaustive (the pattern can never fail to match). Typically, you will thus be limited to product-type definitions @@ -411,7 +443,6 @@ match List.map succ (l1 @ l2) with | _ -> assert false ``` - * Global definition with destructuring `let` statements should be rewritten with explicit pattern-matching and tuples: @@ -423,13 +454,13 @@ let x, y, l = | _ -> assert false ``` - > > **Justification**: There is no way to make the pattern-matching > exhaustive if you use general destructuring `let` bindings. > -#### Sequence warnings and `let _ = ...` +#### Sequence warnings and `let _ = ...` + When the compiler emits a warning about a sequential expression type, you must explicitly indicate that you want to ignore this expression's result. To this end: @@ -441,6 +472,7 @@ result. To this end: List.map f l; print_newline () ``` + write ```ocaml @@ -448,7 +480,6 @@ let _ = List.map f l in print_newline () ``` - * You can also use the predefined function `ignore : 'a -> unit`, which ignores its argument to return `unit`. @@ -458,7 +489,6 @@ ignore (List.map f l); print_newline () ``` - * Regardless, the best way to suppress this warning is to understand why the compiler emits it. The compiler warns you because your code computes a result that is useless since it's @@ -480,6 +510,7 @@ print_newline () List.iter f l; print_newline () ``` + In actual programs, the suitable (side-effect-only) function may not exist and must be written. Frequently, a careful separation of the procedural part from the functional part of the function @@ -493,11 +524,10 @@ let add x y = print_newline (); x + y;; ``` + into the clearer, separate definition and change old calls to `add` accordingly. - - In any case, use the `let _ = ...` construction exactly in those cases where you want to ignore a result. Don't systematically replace sequences with this construction. @@ -511,7 +541,8 @@ sequences with this construction. > e3 > ``` -### The `hd` and `tl` Functions +### The `hd` and `tl` Functions + Don't use the `hd` and `tl` functions, but rather pattern-match the list argument explicitly. @@ -522,8 +553,10 @@ argument explicitly. > functions. > -### Loops -#### `for` loops +### Loops + +#### `for` loops + To simply traverse an array or a string, use a `for` loop. @@ -532,6 +565,7 @@ for i = 0 to Array.length v - 1 do ... done ``` + If the loop is complex or returns a result, use a recursive function. @@ -575,7 +609,8 @@ programs from algorithm courses where they were proved. > invariants, an interesting but difficult sport. > -### Exceptions +### Exceptions + Don't be afraid to define your own exceptions in your programs, but on the other hand, use as many exceptions predefined by the system as possible. For example, every search function that fails should raise the @@ -604,7 +639,8 @@ with x -> close_in ic; close_out oc; raise x > computation will continue anyway!). > -### Data Structures +### Data Structures + One of the great strengths of OCaml is the power of definable data structures and the simplicity of manipulating them. So you must take advantage of this to the fullest extent! Don't hesitate to @@ -686,17 +722,20 @@ types' definitions are then questionable: type switch = On | Off type bit = One | Zero ``` + The same objection is admissible for enumerated types represented as integers when those integers have an evident interpretation with respect to the represented data. -### When to Use Mutables +### When to Use Mutables + Mutable values are useful and sometimes indispensable for simple and clear programming. Nevertheless, you must use them with discernment because OCaml's normal data structures are immutable. They are preferred for the clarity and safety of programming they allow. -### Iterators +### Iterators + OCaml's iterators are a powerful and useful feature. However, you should not overuse them nor neglect them. They are provided by libraries and have every chance of being correct and @@ -708,6 +747,7 @@ Write: ```ocaml let square_elements elements = List.map square elements ``` + rather than: ```ocaml @@ -715,12 +755,14 @@ let rec square_elements = function | [] -> [] | elem :: elements -> square elem :: square_elements elements ``` + On the other hand, avoid writing: ```ocaml let iterator f x l = List.fold_right (List.fold_left f) [List.map x l] l ``` + even though you get: ```ocaml @@ -728,13 +770,14 @@ even though you get: List.fold_right (List.fold_left f) [List.map x l] l;; iterator (fun l x -> x :: l) (fun l -> List.rev l) [[1; 2; 3]] ``` + In case of express need, be sure to add an explanatory comment. In my opinion, it's absolutely necessary! -### How to Optimize Programs +### How to Optimize Programs > > **Pseudo law of optimisation**: No optimisation *a priori*.
-> No optimisation *a posteriori* either. +> No optimisation *a posteriori* either. > Above all, program simply and clearly. Don't start optimising until the @@ -751,7 +794,8 @@ program that poses a problem. > efficiency is of prime importance. > -### How to Choose Between Classes and Modules +### How to Choose Between Classes and Modules + Use OCaml classes when you need inheritance, i.e., incremental refinement of data and their functionality. @@ -762,7 +806,8 @@ Use modules when the data structures are fixed and their functionality is equally fixed or it's enough to add new functions in the programs which use them. -### Clarity of OCaml Code +### Clarity of OCaml Code + The OCaml language includes powerful constructs that allow simple and clear programming. The main problem to obtain crystal clear programs is to use them appropriately. @@ -779,7 +824,8 @@ to use the language construct that expresses the computation to implement the algorithm in the most natural and easiest way. -#### Style dangers +#### Style dangers + Concerning programming styles, one can usually observe the two symmetrical problematic behaviors. On one hand, the “all imperative” way (*systematic* usage of loops and assignment), and on @@ -788,7 +834,7 @@ assignments). The “100% object” style will certainly appear in the future. * **The “too much imperative” danger**: - * It is a bad idea to use imperative style to code a function that + * It is a bad idea to use imperative style to code a function that is *naturally* recursive. For instance, to compute the length of a list, you shouldn't write: @@ -801,6 +847,7 @@ let list_length l = done; !res;; ``` + in place of the following recursive function that's so simple and clear: @@ -809,10 +856,10 @@ let rec list_length = function | [] -> 0 | _ :: l -> 1 + list_length l ``` + (For those that would contest the equivalence of those two versions, see the [note below](#imperative-and-functional-versions-of-listlength)). - * Another common “over-imperative error” in the imperative world is not to systematically choose the simple `for` loop to iterate on a vector's element, but instead to use a complex `while` loop with @@ -823,22 +870,23 @@ versions, see the [note below](#imperative-and-functional-versions-of-listlength the record-type definitions should be implicit. * **The “too much functional” danger**: - * The programmer that adheres to this dogma avoids + * The programmer that adheres to this dogma avoids using arrays and assignment. In the most severe cases, one observes a complete denial of writing any imperative construction, even when it's evidently the most elegant way to solve the problem. - * Characteristic symptoms: systematic rewriting `for` loops + * Characteristic symptoms: systematic rewriting `for` loops with recursive functions, using lists in contexts where imperative data structures seem to be mandatory to anyone, passing numerous global parameters of the problem to every function, even when a global reference perfectly avoid these spurious parameters that are mainly invariants that must be repeatedly passed. - * This programmer feels that the `mutable` keyword in record-type + * This programmer feels that the `mutable` keyword in record-type definitions should be suppressed from the language. -#### OCaml code generally considered unreadable +#### OCaml code generally considered unreadable + The OCaml language includes powerful constructs which allow simple and clear programming. However, the power of these constructs also lets you write uselessly complicated code to the point where you get a perfectly @@ -852,6 +900,7 @@ Here are a number of common ways to write overly-complicated code: let flush_ps () = if not !psused then psused := true ``` + or (more subtle) ```ocaml @@ -859,7 +908,6 @@ let sync b = if !last_is_dvi <> b then last_is_dvi := b ``` - * Code one construct with another. For example, code a `let ... in` by the application of an anonymous function to an argument. You would write
@@ -868,6 +916,7 @@ let sync b = (fun x y -> x + y) e1 e2 ``` + instead of simply writing ```ocaml @@ -876,10 +925,8 @@ and y = e2 in x + y ``` - * Systematically code sequences with `let in` bindings. - * Mix computations and side effects, particularly in function calls. Recall that the evaluation order of function call arguments is unspecified, which implies that you must not mix side effects and @@ -889,7 +936,6 @@ x + y albeit without endangering the program semantics. This should be absolutely forbidden. - * Misuse of iterators and higher-order functions (i.e., over- or underuse). For example, it's better to use `List.map` or `List.iter` than to write their equivalents inline by using your own @@ -897,7 +943,6 @@ x + y `List.map` or `List.iter`, but rather write their equivalents in terms of `List.fold_right` and `List.fold_left`. - * Another efficient way to write unreadable code is to mix all or some of these methods. For example: @@ -908,17 +953,18 @@ x + y temp));; ``` - If you naturally write the program `print_string "Hello world!"` in this way, please submit your work to the [Obfuscated OCaml Contest](mailto:Pierre.Weis@inria.fr). ## Managing Program Development + Below are tips from veteran OCaml programmers that have served in developing the compilers. These are good examples of large, complex programs developed by small teams. -### How to Edit Programs +### How to Edit Programs + Many developers nurture a kind of veneration towards writing their programs in the Emacs editor (GNU Emacs, in general). The editor interfaces with the language well because it is capable of syntax-coloring @@ -938,7 +984,8 @@ succession of `` CTRL-X-` `` commands permits correction of all signalled errors; finally, the cycle begins again with a new recompilation launched by `CTRL-C-CTRL-C`. -#### Other Emacs tricks +#### Other Emacs tricks + The `ESC-/` command (dynamic-abbrev-expand) automatically completes the word in front of the cursor with one of the words in a file being edited. This lets you always choose meaningful @@ -955,7 +1002,8 @@ messages” from `grep` are compatible with the `` CTRL-X-` `` usage, which automatically takes you to the file and the place where the string is found. -### How to Edit With the Interactive System +### How to Edit With the Interactive System + Under Unix: use the line editor `ledit`, which offers great editing capabilities “à la Emacs” (including `ESC-/`!) as well as a history mechanism that lets you retrieve previously-typed commands and even @@ -963,13 +1011,15 @@ retrieve commands from one session to another. `ledit` is written in OCaml and can be freely downnloaded [here](ftp://ftp.inria.fr/INRIA/Projects/cristal/caml-light/bazar-ocaml/ledit.tar.gz). -### How to Compile +### How to Compile + The `make` utility is indispensable for managing the compilation and recompilation of programs. Sample `make` files can be found on [The Hump](https://web.archive.org/web/20170809105617/http://caml.inria.fr/cgi-bin/hump.en.cgi). You can also consult the `Makefiles` for the OCaml compilers. -### How to Develop as a Team: Version Control +### How to Develop as a Team: Version Control + Users of the [Git](https://git-scm.com/) software version control system never run out of good things to say about the productivity gains it brings. This system supports managing development by a programming team @@ -994,27 +1044,28 @@ consider these style guidelines when doing it manually. > keyboard, so press it as often as necessary! > -### Delimiters +### Delimiters + A space should always follow a delimiter symbol, and spaces should surround operator symbols. It has been a great step forward in typography to separate words by spaces in order to make written texts easier to read. Do the same in your programs if you want them to be readable. +### How to Write Pairs - -### How to Write Pairs A tuple is parenthesised, and the commas therein (delimiters) are each followed by a space: `(1, 2)`, `let triplet = (x, y, z)`... **Commonly accepted exceptions**: - - **Definition of the components of a pair**: In place of + +* **Definition of the components of a pair**: In place of `let (x, y) = ...`, you can write `let x, y = ...`. > **Justification**: The point is to define several values > simultaneously, not to construct a tuple. Moreover, the > pattern is set off nicely between `let` and `=`. - - **Matching several values simultaneously**: It's okay to omit +* **Matching several values simultaneously**: It's okay to omit parentheses around n-tuples when matching several values simultaneously. @@ -1028,20 +1079,20 @@ followed by a space: `(1, 2)`, `let triplet = (x, y, z)`... > being matched are set off by `match` and `with`, while the > patterns are set off nicely by `|` and `->`. +### How to Write Lists -### How to Write Lists Write `x :: l` with spaces around the `::` (since `::` is an infix operator, hence surrounded by spaces) and `[1; 2; 3]` (since `;` is a delimiter, hence followed by a space). -### How to Write Operator Symbols +### How to Write Operator Symbols + Be careful to keep operator symbols separated by spaces. Not only will your formulas be more readable, but you will also avoid confusion with multicharacter operators. (Obvious exceptions to this rule are the symbols `!` and `.`, which are not separated from their arguments.)
Example: write `x + 1` or `x + !y`. - > **Justification**: If you left out the spaces then `x+1` would be > understood, but `x+!y` would change its meaning, since `+!` would > be interpreted as a multicharacter operator. @@ -1079,8 +1130,8 @@ Example: write `x + 1` or `x + !y`. > follow. The space bar is the greatest and best-situated key on the > keyboard. It is the easiest to use because you cannot miss it! +### How to Write Long Character Strings -### How to Write Long Character Strings Indent long character strings with the convention in force at that line, plus an indication of string continuation at the end of each line (a `\` character at the end of the line omits white spaces at the @@ -1093,7 +1144,8 @@ let universal_declaration = ... ``` -### When to Use Parentheses Within an Expression +### When to Use Parentheses Within an Expression + Parentheses are meaningful. They indicate the necessity of using an unusual precedence, so they should be used wisely and not sprinkled randomly throughout programs. To this end, you should know the usual @@ -1101,10 +1153,12 @@ precedences, i.e., the combinations of operations which do not require parentheses. Quite fortunately, this is not complicated if you know a little mathematics or strive to follow the following rules: -#### Arithmetic operators: the same rules as in mathematics +#### Arithmetic operators: the same rules as in mathematics + For example: `1 + 2 * x` means `1 + (2 * x)`. -#### Function application: the same rules as those in mathematics for usage of *trigonometric functions* +#### Function application: the same rules as those in mathematics for usage of *trigonometric functions* + In mathematics you write `sin x` to mean `sin (x)`. In the same way `sin x + cos x` means `(sin x) + (cos x)` not `sin (x + (cos x))`. Use the same conventions in OCaml: write `f x + g x` to mean @@ -1113,20 +1167,23 @@ This convention generalises **to all (infix) operators**: `f x :: g x` means `(f x) :: (g x)`, `f x @ g x` means `(f x) @ (g x)`, and `failwith s ^ s'` means `(failwith s) ^ s'`, *not* `failwith (s ^ s')`. -#### Comparisons and Boolean operators +#### Comparisons and Boolean operators + Comparisons are infix operators, so the preceding rules apply. This is why `f x < g x` means `(f x) < (g x)`. For type reasons (and no other sensible interpretation), the expression `f x < x + 2` means `(f x) < (x + 2)`. Similarly, `f x < x + 2 && x > 3` means `((f x) < (x + 2)) && (x > 3)`. -#### The relative precedences of the Boolean operators are those of mathematics +#### The relative precedences of the Boolean operators are those of mathematics + Although mathematicians have a tendency to overuse parentheses, the Boolean “or” operator is analogous to addition and the “and” to multiplication. So, just as `1 + 2 * x` means `1 + (2 * x)`, `true || false && x` means `true || (false && x)`. -### How to Delimit Constructs in Programs +### How to Delimit Constructs in Programs + When it is necessary to delimit syntactic constructs in programs, use the keywords `begin` and `end` as delimiters rather than parentheses. However, using parentheses is acceptable if you do it in a consistent, @@ -1136,7 +1193,8 @@ This explicit delimiting of constructs essentially concerns pattern-matching constructs or sequences embedded within `if then else` constructs. -#### `match` construct in a `match` construct +#### `match` construct in a `match` construct + When a `match ... with` or `try ... with` construct appears in a pattern-matching clause, it is absolutely necessary to delimit this embedded construct (otherwise subsequent clauses of the enclosing @@ -1153,7 +1211,9 @@ match x with | 2 -> ... ``` -#### Sequences inside branches of `if` + +#### Sequences inside branches of `if` + In the same way, a sequence which appears in the `then` or `else` part of a conditional must be delimited: @@ -1168,7 +1228,6 @@ end else begin end ``` - ## Indentation of Programs > > **Landin's pseudo law**: Treat your program's indentation as if @@ -1189,39 +1248,40 @@ So each time, you must choose between the different styles suggested.
The only absolute rule is the first below. -### Consistency of Indentation +### Consistency of Indentation + Choose a generally accepted style of indentation, then use it systematically throughout the whole application. -### Width of the Page +### Width of the Page + The page is 80 columns wide. > **Justification**: This width makes it possible to read the code on > all displays and to print it in a legible font on a standard sheet. +### Height of the Page -### Height of the Page A function should always fit within one screenful (of about 70 lines), or in exceptional cases two, at the very most three. To go beyond this is unreasonable. - > **Justification**: When a function goes beyond one screenful, it's > time to divide it into subproblems and handle them independently. > Beyond a screenful, one gets lost in the code. The indentation is not > readable and is difficult to keep correct. +### How Much to Indent -### How Much to Indent The change in indentation between successive lines of the program is generally 1 or 2 spaces. Pick an amount to indent and stick with it throughout the program. -### Using Tab Stops +### Using Tab Stops + Using the tab character (ASCII character 9) is absolutely *not* recommended. - > **Justification**: Between one display and another, the indentation of > the program changes completely. It can also become completely wrong > if the programmer used both tabulations and spaces to indent the @@ -1235,7 +1295,8 @@ recommended. > **Answer**: It seems almost impossible to use this method since you > should always use tabulations to indent, which is hard and unnatural. -### How to Indent Operations +### How to Indent Operations + When an operator takes complex arguments, or in the presence of multiple calls to the same operator, start the next the line with the operator, and don't indent the rest of the operation. For example: @@ -1260,6 +1321,7 @@ x + y + z + “large expression” ``` + write @@ -1269,6 +1331,7 @@ let t = expression” in x + y + z + t ``` + You most certainly must bind expressions too large to be written in one operation when using a combination of operators. In place of the unreadable expression @@ -1279,6 +1342,7 @@ the unreadable expression / (“large expression”) ``` + write @@ -1288,6 +1352,7 @@ let u = expression” in (x + y + z * t) / u ``` + These guidelines extend to all operators. For example: @@ -1299,8 +1364,8 @@ x :: y :: z + 1 :: t :: u ``` +### How to Indent Global `let ... ;;` Definitions -### How to Indent Global `let ... ;;` Definitions The body of a function defined globally in a module is generally indented normally. However, it's okay to treat this case specially to better offset the definition. @@ -1344,7 +1409,6 @@ let f x = function > **Criticism**: An unpleasant exception to the normal indentation. > - * The body is justified just under the name of the defined function. @@ -1362,8 +1426,8 @@ let f x = > **Criticism**: You run into the right margin too quickly. > +### How to Indent `let ... in` Constructs -### How to Indent `let ... in` Constructs The expression following a definition introduced by `let` is indented to the same level as the keyword `let`, and the keyword `in`, which introduces it, is written at the end of the line: @@ -1407,8 +1471,10 @@ Mult_expression (new_expr, new_expr) > **Criticism**: Lack of consistency. > -### How to Indent `if ... then ... else ... ` -#### Multiple branches +### How to Indent `if ... then ... else ...` + +#### Multiple branches + Write conditions with multiple branches at the same level of indentation: @@ -1433,6 +1499,7 @@ if cond3 then e3 else e4 ``` + If expressions in the branches of multiple conditions have to be enclosed (when they include statements for instance), write: @@ -1446,6 +1513,7 @@ if cond2 then begin end else if cond3 then ... ``` + Some suggest another method for multiple conditionals: starting each line by the keyword `else`: @@ -1467,7 +1535,8 @@ else if cond3 ... Yet again, choose your style and use it systematically. -#### Single branches +#### Single branches + Several styles are possible for single branches, according to the size of the expressions in question and especially the presence of `begin`, `end`, or `(` `)` delimiters for these expressions. @@ -1484,6 +1553,7 @@ are used: > e2 > ) > ``` +> > Or alternatively first `begin` at beginning of line: > > ```ocaml @@ -1503,6 +1573,7 @@ In fact, the conditional's indentation depends on their expressions' size. > ```ocaml > if cond then e1 else e2 > ``` +> > If the expressions making up a conditional are purely functional > (without side effects), we advocate binding them within the > conditional by using `let e = ... in` when they're too big to fit on a single @@ -1561,8 +1632,10 @@ In fact, the conditional's indentation depends on their expressions' size. > > ) else e2 > > ``` -### How to Indent Pattern-Matching Constructs -#### General principles +### How to Indent Pattern-Matching Constructs + +#### General principles + All the pattern-matching clauses are introduced by a vertical bar, *including* the first one. @@ -1589,7 +1662,8 @@ Then indent normally, starting from the beginning of the clause's pattern. Arrows of pattern-matching clauses should not be aligned. -#### `match` or `try` +#### `match` or `try` + For a `match` or a `try`, align the clauses with the beginning of the construct: @@ -1604,6 +1678,7 @@ try f x with | Not_found -> ... | Failure "not yet implemented" -> ... ``` + Put the keyword `with` at the end of the line. If the preceding expression extends beyond one line, put `with` on its own line: @@ -1621,7 +1696,8 @@ with > the program enters the pattern-matching part of the construct. > -#### Indenting expressions inside clauses +#### Indenting expressions inside clauses + If the expression on the right of the pattern-matching arrow is too large, cut the line after the arrow. @@ -1634,6 +1710,7 @@ match lam with size_lambda lam1 + size_lambda lam2 | Var v -> ``` + Some programmers generalise this rule to all clauses as soon as one expressions overflows. They will then indent the last clause like this: @@ -1642,6 +1719,7 @@ expressions overflows. They will then indent the last clause like this: | Var v -> 1 ``` + Other programmers go one step further and apply this rule systematically to any clause of any pattern-matching. @@ -1665,7 +1743,8 @@ let rec fib = function > OCaml programs! > -#### Pattern-matching in anonymous functions +#### Pattern-matching in anonymous functions + Similarly to `match` or `try`, pattern-matching of anonymous functions, starting with `function`, are indented with respect to the `function` keyword: @@ -1679,7 +1758,9 @@ map | Var v -> 1) lambda_list ``` -#### Pattern-matching in named functions + +#### Pattern-matching in named functions + Pattern-matching in functions defined by `let` or `let rec` gives rise to several reasonable styles that obey the preceding pattern-matching rules (the one for anonymous functions being evidently excepted). See @@ -1697,8 +1778,11 @@ let rec size_lambda accu = function | App (lam1, lam2) -> size_lambda (size_lambda accu lam1) lam2 | Var v -> succ accu ``` -### Bad Indentation of Pattern-Catching constructs -#### No *beastly* indentation of functions and case analyses. + +### Bad Indentation of Pattern-Catching constructs + +#### No *beastly* indentation of functions and case analyses + This consists in indenting normally under the keyword `match` or `function` that has previously been pushed to the right. Don't write: @@ -1708,6 +1792,7 @@ let rec f x = function | [] -> ... ... ``` + but choose to indent the line under the `let` keyword: @@ -1721,7 +1806,8 @@ let rec f x = function > doubtful. > -#### No *beastly* alignment of the `->` symbols in pattern-matching clauses. +#### No *beastly* alignment of the `->` symbols in pattern-matching clauses + Careful alignment of pattern-matching arrows is considered bad practice, as exemplified in the following fragment: @@ -1739,8 +1825,10 @@ let f = function > In this case, it's better not to align the arrows in the first place!). > -### How to Indent Function Calls -#### Indentation to the function's name: +### How to Indent Function Calls + +#### Indentation to the function's name + No problem arises except for functions with many arguments—or very complicated arguments—which can't fit on the same line. You must indent the expressions with respect to the fucntion's name (1 @@ -1760,9 +1848,10 @@ construction. > explicitly define the evaluation order. > +## Notes + +### Imperative and Functional Versions of `list_length` -## Notes -### Imperative and Functional Versions of `list_length` The two versions of `list_length` are not completely equivalent in terms of complexity. The imperative version uses a constant amount of stack room to execute, whereas the functional version needs to store @@ -1781,12 +1870,14 @@ let list_length l = | _ :: l -> loop (accu + 1) l in loop 0 l ``` + This way, you get a program that has the same computational properties as the imperative program with the additional clarity and natural look of an algorithm that performs pattern-matching and recursive calls to handle an argument that belongs to a recursive sum data type. ## Credits + Original translation from French: [Ruchira Datta](mailto:datta@math.berkeley.edu). diff --git a/data/tutorials/guides/rs_01_common_error_messages.md b/data/tutorials/guides/rs_01_common_error_messages.md index 13483b9b22..269ce02750 100644 --- a/data/tutorials/guides/rs_01_common_error_messages.md +++ b/data/tutorials/guides/rs_01_common_error_messages.md @@ -11,7 +11,9 @@ messages that are emitted by the OCaml compilers. Longer explanations are usually given in dedicated sections of this tutorial. ## Type Errors + ### `This expression has type ... but is here used with type ...` + When the type of an object is not compatible with the context in which it is used, it is frequent to obtain this kind of message: @@ -21,6 +23,7 @@ Line 1, characters 5-8: Error: This expression has type float but an expression was expected of type int ``` + "This expression has type *X* but is here used with type *Y*" means that if the contents of the expression is isolated (2.5), its type is inferred as *X* (float). But the context, i.e. everything which is @@ -32,6 +35,7 @@ More disturbing is the following message: ```text This expression has type my_type but is here used with type my_type ``` + This error happens often while testing some type definitions using the interactive toplevel. In OCaml, it is perfectly legal to define a type with a name @@ -54,6 +58,7 @@ Error: This expression has type my_type/1 toplevel session. Some toplevel values still refer to old versions of this type. Did you try to redefine them? ``` + For the compiler, the second definition of my_type is totally independent from the first definition. So we have defined two types which have the same name. Since "a" was defined earlier, it belongs to @@ -64,6 +69,7 @@ the same name for the same type in the same module, which is highly discouraged. ### `Warning: This optional argument cannot be erased` + Functions with optional arguments must have at least one non-labelled argument. For instance, this is not OK: @@ -75,16 +81,19 @@ Line 1, characters 9-14: Warning 16 [unerasable-optional-argument]: this optional argument cannot be erased. val f : ?x:int -> ?y:int -> unit = ``` + The solution is simply to add one argument of type unit, like this: ```ocaml # let f ?(x = 0) ?(y = 0) () = print_int (x + y);; val f : ?x:int -> ?y:int -> unit -> unit = ``` + See the [Labels](/docs/labels) section for more details on functions with labelled arguments. ### `The type of this expression... contains type variables that cannot be generalized` + This happens in some cases when the full type of an object is not known by the compiler when it reaches the end of the compilation unit (file) but for some reason it cannot remain polymorphic. Example: @@ -93,6 +102,7 @@ but for some reason it cannot remain polymorphic. Example: # let x = ref None;; val x : '_weak1 option ref = {contents = None} ``` + triggers the following message during the compilation: ```text @@ -106,6 +116,7 @@ Solution: help the compiler with a type annotation, like for instance: # let x : string option ref = ref None;; val x : string option ref = {contents = None} ``` + or: ```ocaml env=ref @@ -130,6 +141,7 @@ using `x` later, the compiler can infer the type of `x`: # x := Some 0;; - : unit = () ``` + Now `x` has a known type: ```ocaml env=ref @@ -138,7 +150,9 @@ Now `x` has a known type: ``` ## Pattern Matching Warnings and Errors + ### `This pattern is unused` + This warning should be considered as an error, since there is no reason to intentionally keep such code. It may happen when the programmer introduced a catch-all pattern unintentionally such as in the following @@ -158,6 +172,7 @@ Only the first match will be used to evaluate the guard expression. (See manual section 11.5) val test_member : 'a -> 'a * 'a -> bool = ``` + Obviously, the programmer had a misconception of what OCaml's pattern matching is about. Remember the following: @@ -178,7 +193,9 @@ will ever be tested. This leads to the following results: # test_member 1 (0, 1);; - : bool = false ``` + ### `This pattern-matching is not exhaustive` + OCaml's pattern matching can check whether a set of patterns is exhaustive or not, based on the *type* only. So in the following example, the compiler doesn't know what range of ints the "mod" operator @@ -190,12 +207,14 @@ let is_even x = | 0 -> true | 1 | -1 -> false ``` + A short solution without pattern matching would be: ```ocaml # let is_even x = x mod 2 = 0;; val is_even : int -> bool = ``` + In general, that kind of simplification is not possible and the best solution is to add a catch-all case which should never be reached: @@ -209,7 +228,9 @@ val is_even : int -> bool = ``` ## Problems Recompiling Valid Programs + ### `x.cmi is not a compiled interface` + When recompiling some old program or compiling a program from an external source that was not cleaned properly, it is possible to get this error message: @@ -220,10 +241,11 @@ some_module.cmi is not a compiled interface It means that some_module.cmi is not valid according to the *current version* of the OCaml compiler. Most of the time, removing the old -compiled files (*.cmi, *.cmo, *.cmx, ...) and recompiling is +compiled files (*.cmi,*.cmo, *.cmx, ...) and recompiling is sufficient to solve this problem. ### `Warning: Illegal backslash escape in string` + Recent versions of OCaml warn you against unprotected backslashes in strings since they should be doubled. Such a message may be displayed when compiling an older program, and can be turned off with the `-w x` diff --git a/data/tutorials/guides/rs_02_comparison_of_standard_containers.md b/data/tutorials/guides/rs_02_comparison_of_standard_containers.md index abcc126564..ff39f0d2a1 100644 --- a/data/tutorials/guides/rs_02_comparison_of_standard_containers.md +++ b/data/tutorials/guides/rs_02_comparison_of_standard_containers.md @@ -6,7 +6,7 @@ description: > category: "Resources" --- -This is a rough comparison of the different container types +This is a rough comparison of the different container types provided by the OCaml standard library. In each case, _n_ is the number of valid elements in the container. @@ -17,6 +17,7 @@ you can read the [documentation](/manual/api/index.html) about each of the modul is also instructive to read the corresponding implementation. ## Lists: Immutable Singly-Linked Lists + Adding an element always creates a new list _l_ from an element _x_ List _tl_. _tl_ remains unchanged, but it is not copied either. @@ -30,6 +31,7 @@ Well-suited for: I/O, pattern-matching Not very efficient for: random access, indexed elements ## Arrays: Mutable Vectors + Arrays are mutable data structures with a fixed length and random access. * Adding an element (by creating a new array): _O(n)_ @@ -40,6 +42,7 @@ Arrays are mutable data structures with a fixed length and random access. Well-suited for the following cases: dealing with sets of elements of known size, accessing elements by numeric index, and modifying in-place elements. Basic arrays have a fixed length. ## Strings: Immutable Vectors + Strings are very similar to arrays, but they are immutable. Strings are specialised for storing chars (bytes) and have some convenient syntax. Strings have a fixed length. For extensible strings, the standard buffer @@ -51,6 +54,7 @@ module can be used (see below). * Finding an element: _O(n)_ ## Set and Map: Immutable Trees + Like lists, these are immutable, and they may share some subtrees. These trees are a good solution for keeping older versions of sets of items. @@ -62,6 +66,7 @@ Sets and maps are very useful in compilation and metaprogramming, but in other situations, hash tables are often more appropriate (see below). ## Hashtbl: Automatically Growing Hash Tables + OCaml hash tables are mutable data structures, which are a good solution for storing (key, data) pairs in one single place. @@ -73,6 +78,7 @@ for storing (key, data) pairs in one single place. * Finding an element: _O(1)_ ## Buffer: Extensible Strings + Buffers provide an efficient way to accumulate a byte sequence in a single place. They are mutable. @@ -84,6 +90,7 @@ single place. They are mutable. * Accessing cell `i`: _O(1)_ ## Queue + OCaml queues are mutable first-in-first-out (FIFO) data structures. * Adding an element: _O(1)_ @@ -91,6 +98,7 @@ OCaml queues are mutable first-in-first-out (FIFO) data structures. * Length: _O(1)_ ## Stack + OCaml stacks are mutable last-in-first-out (LIFO) data structures. They are just like lists except they are mutable, i.e., adding an element doesn't create a new stack but simply adds it to the stack. diff --git a/data/tutorials/language/0it_00_values_functions.md b/data/tutorials/language/0it_00_values_functions.md index cbbd8f41c9..8d374ff9ad 100644 --- a/data/tutorials/language/0it_00_values_functions.md +++ b/data/tutorials/language/0it_00_values_functions.md @@ -114,6 +114,11 @@ Arbitrary combinations of chaining or nesting are allowed. In both examples, `d` and `e` are local definitions. +## Forms of Pattern Matching + +[Pattern matching](https://en.wikipedia.org/wiki/Pattern_matching) is a programming language construct that generalizes case analysis, it makes subexpression inspection possible and applies to values of any type. + +In the following sections, we explore matching inside `let` bindings, which is a special case. In the next chapter on [Basic Data Types and Pattern Matching](/docs/basic-data-types), we examine pattern matching in general cases using `match...with`. The chapter on [Error Handling](/docs/error-handling) explores how destructuring values aids in error handling when using `try...with`. ## Pattern Matching in Definitions @@ -126,6 +131,7 @@ When pattern matching only has one case, it can be used in name definitions and name may be defined. This applies to tuples, records, and custom single-variant types. + ### Pattern Matching on Tuples A common case is tuples. It allows the creation of two names with a single `let`. @@ -194,7 +200,6 @@ Above, the pattern does not contain any identifier, meaning no name is defined. **Note**: In order for compiled files to only evaluate an expression for its side effects, you must write them after `let () =`. - ### Pattern Matching on User-Defined Types @@ -209,15 +214,124 @@ val forename : string = "Robin" val surname : string = "Milner" ``` +### Nested Pattern Matching on User-Defined Types + +Pattern matching also works with nested user-defined types. In the example below, we deconstruct nested tuples: + +```ocaml +# let (name, (street, city, zip), (email, phone)) = + ("John Doe", ("123 Elm St", "Springfield", 12345), ("john@example.com", 1234567890));; +val name : string = "John Doe" +val street : string = "123 Elm St" +val city : string = "Springfield" +val zip : int = 12345 +val email : string = "john@example.com" +val phone : int = 1234567890 +``` + +In the following example, we deconstruct a tuple nested within a record. + +Records require explicit type definitions wherein field names are annotated with types. We first define a `person` record type, then create an instance of that type named `jane`: + +```ocaml +# type person = { + name : string; + street : string; + city : string; + zip : int; + contact: string * int; + };; +type person = { + name : string; + street : string; + city : string; + zip : int; + contact : string * int; + +# let jane = { + name = "Jane Doe"; + street = "123 Elm St"; + city = "Springfield"; + zip = 12345; + contact = ("jane@example.com", 1234567890); + };; +val jane : person = + {name = "Jane Doe"; street = "123 Elm St"; city = "Springfield"; zip = 12345; + contact = ("jane@example.com", 1234567890)} +``` + +The following examples demonstrate two methods by which we can extract Jane's `email` and `phone` number data in the nested `contact` tuple. We will do so first by using nested deconstruction, then demonstrate another approach by first extracting `content` followed by accessing the `email` and `phone` by deconstructing `contact`. + +First, lets use nested deconstruction to access the contents of the `contact` tuple directly: + +```ocaml +# let { name; street; city; zip; contact = (email, phone) } = jane;; +val name : string = "Jane Doe" +val street : string = "123 Elm St" +val city : string = "Springfield" +val zip : int = 12345 +val email : string = "jane@example.com" +val phone : int = 1234567890 +``` + +Notice that `contact` is not available in our top-level scope: + +```ocaml +# contact;; +Error: Unbound value contact +``` + +This is because "contact" is not a top-level definition; rather, it is a local definition from deconstructive pattern-matching. + +Next, we demonstrate the two-phase approach for accessing `email` and `phone`. This brings `contact` into our top-level scope and requires two steps: + +```ocaml +(* Step 1: deconstruct all record fields *) +# let { name; street; city; zip; contact } = jane;; +val name : string = "Jane Doe" +val street : string = "123 Elm St" +val city : string = "Springfield" +val zip : int = 12345 +val contact : string * int = ("jane@example.com", 1234567890) + +(* Step 2: deconstruct the tuple *) +# let ( email, phone ) = contact;; +val email : string = "jane@example.com" +val phone : int = 1234567890 +``` + +Notice that `contact` is now available at the top-level as a bound variable: + +```ocaml +# contact;; +- : string * int = ("jane@example.com", 1234567890) +``` + ### Discarding Values Using Pattern Matching - -As seen in the last example, the catch-all pattern (`_`) can be used in definitions. + +When pattern matching, it is possible to discard or ignore values that are not desired. The method by which this is done depends on the data structure being destructured. + +Continuing from the above `jane` record example, we can simply omit the `zip` field in the pattern if we don't want to bind it to a variable: + ```ocaml -# let (_, y) = List.split [(1, 2); (3, 4); (5, 6); (7, 8)];; -val y : int list = [2; 4; 6; 8] +# let { name; street; city; contact = (email, phone) } = john;; +val name : string = "Nohn Doe" +val street : string = "123 Elm St" +val city : string = "Springfield" +val email : string = "jane@example.com" +val phone : int = 1234567890 ``` -The `List.split` function returns a pair of lists. We're only interested in the second list, we give it the name `y` and discard the first list by using `_`. +Tuples behave differently from records; contained data is anonymous, and its position is used to access it. To discard the `email` value from the tuple of the `contact` field, we need to use the catch-all pattern (`_`): + +```ocaml +# let { name; street; city; contact = (_, phone) } = john;; +val name : string = "Jane Doe" +val street : string = "123 Elm St" +val city : string = "Springfield" +val phone : int = 1234567890 +``` + ## Scopes and Environments diff --git a/data/tutorials/language/0it_01_basic_datatypes.md b/data/tutorials/language/0it_01_basic_datatypes.md index b2d8b96e5e..0d775399ba 100644 --- a/data/tutorials/language/0it_01_basic_datatypes.md +++ b/data/tutorials/language/0it_01_basic_datatypes.md @@ -11,7 +11,7 @@ prerequisite_tutorials: ## Introduction -This document covers atomic types, such as integers and Booleans; predefined compound types, like strings and lists; and user-defined types, namely variants and records. We show how to pattern matching on those types. +This document covers atomic types, such as integers and Booleans; predefined compound types, like strings and lists; and user-defined types, namely variants and records. We show how to pattern match on those types. In OCaml, there are no type checks at runtime, and values don't change type unless explicitly converted. This is what being statically- and strongly-typed means. This allows safe processing of structured data. @@ -33,6 +33,7 @@ The goal of this tutorial is to provide for the following capabilities: #### Integers The `int` type is the default and basic integer type in OCaml. When you enter a whole number, OCaml recognises it as an integer, as shown in this example: + ```ocaml # 42;; - : int = 42 @@ -49,6 +50,7 @@ There are no dedicated types for unsigned integers in OCaml. Bitwise operations Float numbers have type `float`. OCaml does not perform any implicit type conversion between values. Therefore, arithmetic expressions can't mix integers and floats. Arguments are either all `int` or all `float`. Arithmetic operators on floats are not the same, and they are written with a dot suffix: `+.`, `-.`, `*.`, `/.`. + ```ocaml # let pi = 3.14159;; val pi : float = 3.14159 @@ -64,11 +66,13 @@ Error: This expression has type int but an expression was expected of type Error: This expression has type float but an expression was expected of type int ``` + Operations on `float` are provided by the [`Stdlib`](/manual/api/Stdlib.html) and the [`Float`](/manual/api/Float.html) modules. #### Booleans Boolean values are represented by the type `bool`. + ```ocaml # true;; - : bool = true @@ -83,6 +87,7 @@ Boolean values are represented by the type `bool`. Operations on `bool` are provided by the [`Stdlib`](/manual/api/Stdlib.html) and the [`Bool`](/manual/api/Bool.html) modules. The conjunction “and” is written `&&` and disjunction “or” is written `||`. Both are short-circuited, meaning that they don't evaluate the argument on the right if the left one's value is sufficient to decide the whole expression's value. In OCaml, `if … then … else …` is a _conditional expression_. It has the same type as its branches. + ```ocaml # 3 * if "foo" = "bar" then 5 else 5 + 2;; - : int = 21 @@ -91,6 +96,7 @@ In OCaml, `if … then … else …` is a _conditional expression_. It has the s The test subexpression must have type `bool`. Branches subexpressions must have the same type. Conditional expression and pattern matching on a Boolean are the same: + ```ocaml # 3 * match "foo" = "bar" with true -> 5 | false -> 5 + 2;; - : int = 21 @@ -99,10 +105,12 @@ Conditional expression and pattern matching on a Boolean are the same: #### Characters Values of type `char` correspond to the 256 symbols of the Latin-1 set. Character literals are surrounded by single quotes, as shown below: + ```ocaml # 'd';; - : char = 'd' ``` + Operations on `char` values are provided by the [`Stdlib`](/manual/api/Stdlib.html) and the [`Char`](/manual/api/Char.html) modules. The module [`Uchar`](/manual/api/Uchar.html) provides support for Unicode characters. @@ -116,10 +124,12 @@ Strings are finite and fixed-sized sequences of char values. Strings are immutab --> Strings are immutable, meaning it is impossible to change a character's value inside a string. + ```ocaml # "hello" ^ " " ^ "world!";; - : string = "hello world!" ``` + Strings are finite and fixed-sized sequences of `char` values. The string concatenation operator symbol is `^`. Indexed access to string characters is possible using the following syntax: + ```ocaml # "buenos dias".[4];; - : char : 'o' ``` + Operations on `string` values are provided by the [`Stdlib`](/manual/api/Stdlib.html) and the [`String`](/manual/api/String.html) modules. #### Byte Sequences @@ -143,6 +155,7 @@ Moved intro pp to after example, as it contains the definition. Perhaps a short # String.to_bytes "hello";; - : bytes = Bytes.of_string "hello" ``` + Like strings, byte sequences are finite and fixed-sized. Each individual byte is represented by a `char` value. Like arrays, byte sequences are mutable, meaning they can't be extended or shortened, but each component byte may be updated. Essentially, a byte sequence (type `bytes`) is a mutable string that can't be printed. There is no way to write `bytes` literally, so they must be produced by a function. Operations on `bytes` values are provided by the [`Stdlib`](/manual/api/Stdlib.html) and the [`Bytes`](/manual/api/Bytes.html) modules. Only the function `Bytes.get` allows direct access to the characters contained in a byte sequence. Unlike arrays, there is no direct access operator on byte sequences. @@ -153,6 +166,7 @@ The memory representation of `bytes` is four times more compact that `char array #### Arrays Arrays are finite and fixed-sized sequences of values of the same type. Here are a couple of examples: + ```ocaml # [| 0; 1; 2; 3; 4; 5 |];; - : int array = [|0; 1; 2; 3; 4; 5|] @@ -165,19 +179,23 @@ Arrays are finite and fixed-sized sequences of values of the same type. Here are ``` Arrays may contain values of any type. Here arrays are `int array`, `char array`, and `string array`, but any type of data can be used in an array. Usually, `array` is said to be a polymorphic type. Strictly speaking, it is a type operator, and it accepts a type as argument (here `int`, `char`, and `string`) to form another type (those inferred here). This is the empty array. + ```ocaml # [||];; - : 'a array = [||] ``` + Remember, `'a` ("alpha") is a type parameter that will be replaced by another type. Like `string` and `bytes`, arrays support direct access, but the syntax is not the same. + ```ocaml # [| 'x'; 'y'; 'z' |].(2);; - : char = 'z' ``` Arrays are mutable, meaning they can't be extended or shortened, but each element may be updated. + ```ocaml # let letter = [| 'v'; 'x'; 'y'; 'z' |];; val letter : char array = [|'v'; 'x'; 'y'; 'z'|] @@ -196,6 +214,7 @@ Operations on arrays are provided by the [`Array`](/manual/api/Array.html) modul #### Lists As literals, lists are very much like arrays. Here are the same previous examples turned into lists. + ```ocaml # [ 0; 1; 2; 3; 4; 5 ];; - : int list = [0; 1; 2; 3; 4; 5] @@ -216,6 +235,7 @@ There are symbols of special importance with respect to lists: - The list constructor operator, written `::` and pronounced “cons,” is used to add a value at the head of a list. Together, they are the basic means to build a list and access the data it stores. For instance, here is how lists are built by successively applying the cons (`::`) operator: + ```ocaml # 3 :: [];; - : int list = [3] @@ -228,6 +248,7 @@ Together, they are the basic means to build a list and access the data it stores ``` Pattern matching provides the basic means to access data stored inside a list. + ```ocaml # match [1; 2; 3] with | x :: u -> x @@ -248,6 +269,7 @@ In the above expressions, `[1; 2; 3]` is the value that is matched over. Each ex #### Options The `option` type is also a polymorphic type. Option values can store any kind of data or represent the absence of any such data. Option values can only be constructed in two different ways: either `None`, when no data is available, or `Some`, otherwise. + ```ocaml # None;; - : 'a option = None @@ -260,6 +282,7 @@ The `option` type is also a polymorphic type. Option values can store any kind o ``` Here is an example of pattern matching on an option value: + ```ocaml # match Some 42 with None -> raise Exit | Some x -> x;; - : int = 42 @@ -283,6 +306,7 @@ Operations on results are provided by the [`Result`](/manual/api/Result.html) mo ### Tuples Here is a tuple containing two values, also known as a pair. + ```ocaml # (3, 'K');; - : int * char = (3, 'K') @@ -293,6 +317,7 @@ That pair contains the integer `3` and the character `'K'`; its type is `int * c This generalises to tuples with 3 or more elements. For instance, `(6.28, true, "hello")` has type `float * bool * string`. The types `int * char` and `float * bool * string` are called _product types_. The `*` symbol is used to denote types bundled together in products. The predefined function `fst` returns the first element of a pair, while `snd` returns the second element of a pair. + ```ocaml # fst (3, 'g');; - : int = 3 @@ -302,6 +327,7 @@ The predefined function `fst` returns the first element of a pair, while `snd` r ``` In the standard library, both are defined using pattern matching. Here is how a function extracts the third element of the product of four types: + ```ocaml # let f x = match x with (h, i, j, k) -> j;; val f : 'a * 'b * 'c * 'd -> 'c = @@ -314,6 +340,7 @@ Note that types `int * char * bool`, `int * (char * bool)`, and `(int * char) * ### Functions The type of functions from type `m` to type `n` is written `m -> n`. Here are a few examples: + ```ocaml # fun x -> x * x;; - : int -> int = @@ -348,7 +375,7 @@ The following example shows that the identity function can apply to arguments of val f : 'a -> 'a = # f 9;; -- : int = 81 +- : int = 9 # f "hello";; - : string = "hello" @@ -367,6 +394,7 @@ val g : int -> int = Executable OCaml code consists primarily of functions, so it's beneficial to make them as concise and clear as possible. The function `g` is defined here using a shorter, more common, and maybe more intuitive syntax. In OCaml, functions may terminate without returning the expected type value by throwing an exception (of type `exn`), which does not appear in its type. There is no way to know if a function may raise an exception without inspecting its code. + ```ocaml # raise;; - : exn -> 'a' = @@ -375,6 +403,7 @@ In OCaml, functions may terminate without returning the expected type value by t Exceptions are discussed in the [Error Handling](/docs/error-handling) guide. Functions may have several parameters. + ```ocaml # fun s r -> s ^ " " ^ r;; - : string -> string -> string = @@ -392,6 +421,7 @@ Like the product type symbol `*`, the function type symbol `->` is not associati Uniquely, the type `unit` has only one value. It is written `()` and pronounced “unit.” The `unit` type has several uses. Mainly, it serves as a token when a function does not need to be passed data or doesn't have any data to return once it has completed its computation. This happens when functions have side effects such as OS-level I/O. Functions need to be applied to something for their computation to be triggered, and they also must return something. When nothing meaningful can be passed or returned, `()` should be used. + ```ocaml # read_line;; - : unit -> string = @@ -401,6 +431,7 @@ The `unit` type has several uses. Mainly, it serves as a token when a function d ``` The function `read_line` reads an end-of-line terminated sequence of characters from standard input and returns it as a string. Reading input begins when `()` is passed. + ```ocaml # read_line ();; foo bar @@ -432,6 +463,7 @@ Variants are also called [_tagged unions_](https://en.wikipedia.org/wiki/Tagged_ The simplest form of a variant type corresponds to an [enumerated type](https://en.wikipedia.org/wiki/Enumerated_type). It is defined by an explicit list of named values. Defined values are called constructors and must be capitalised. For example, here is how variant data types could be defined to represent Dungeons & Dragons character classes and alignment. + ```ocaml # type character_class = | Barbarian @@ -471,6 +503,7 @@ ordering is defined on values following the definition order (e.g., `Druid < Ranger`). Pattern matching can be performed on the types defined above: + ```ocaml # let rectitude_to_french = function | Evil -> "Mauvais" @@ -487,6 +520,7 @@ Note that: #### Constructors With Data It is possible to wrap data in constructors. The following type has several constructors with data (e.g., `Hash of string`) and some without (e.g., `Head`). It represents the different means to refer to a Git [revision](https://git-scm.com/docs/gitrevisions). + ```ocaml # type commit = | Hash of string @@ -508,6 +542,7 @@ type commit = ``` Here is how to convert a `commit` to a `string` using pattern matching: + ```ocaml # let commit_to_string = function | Hash sha -> sha @@ -521,6 +556,7 @@ val commit_to_string : commit -> string = ``` Above, the `function …` construct is used instead of the `match … with …` construct used previously: + ```ocaml let commit_to_string' x = match x with | Hash sha -> sha @@ -532,9 +568,11 @@ let commit_to_string' x = match x with | Merge_head -> "MERGE_HEAD";; val commit_to_string' : commit -> string = ``` + We need to pass an inspected expression to the `match … with …` construct. The `function …` is a special form of an anonymous function that takes a parameter and forwards it to a `match … with …` construct, as shown above. **Warning**: Wrapping product types with parentheses turns them into a single parameter. + ```ocaml # type t = | C1 of int * bool @@ -559,6 +597,7 @@ The constructor `C1` has two parameters of type `int` and `bool`, whilst the con A variant definition referring to itself is recursive. A constructor may wrap data from the type being defined. This is the case for the following definition, which can be used to store JSON values. + ```ocaml # type json = | Null @@ -581,6 +620,7 @@ type json = Both constructors `Array` and `Object` contain values of type `json`. Functions defined using pattern matching on recursive variants are often recursive too. This function checks if a name is present in a whole JSON tree: + ```ocaml # let rec has_field name = function | Array u -> @@ -606,12 +646,14 @@ type 'a option = None | Some of 'a ``` The predefined type `list` is polymorphic in the same sense. It is a variant with two constructors and can hold data of any type. Here is how it is defined in the standard library: + ```ocaml # #show list;; type 'a list = [] | (::) of 'a * 'a list ``` The only magic here is turning constructors into symbols, which we don't cover in this tutorial. The types `bool` and `unit` also are regular variants, with the same magic: + ```ocaml # #show unit;; type unit = () @@ -621,6 +663,7 @@ type bool = false | true ``` Implicitly, product types also behave as variant types. For instance, pairs can be seen as inhabitants of this type: + ```ocaml # type ('a, 'b) pair = Pair of 'a * 'b;; type ('a, 'b) pair = Pair of 'a * 'b @@ -632,9 +675,10 @@ Even integers and floats can be seen as enumerated-like variant types, with many In the end, the only type construction that does not reduce to a variant is the function arrow type. Pattern matching allows the inspection of values of any type, except functions. -#### User-Defined Polymorphic +#### User-Defined Polymorphic Types Here is an example of a variant type that combines constructors with data, constructors without data, polymorphism, and recursion: + ```ocaml # type 'a tree = | Leaf @@ -643,6 +687,7 @@ type 'a tree = Leaf | Node of 'a * 'a tree * 'a tree ``` It can be used to represent arbitrarily labelled binary trees. Assuming such a tree would be labelled with integers, here is a possible way to compute the sum of its integers, using recursion and pattern matching. + ```ocaml # let rec sum = function | Leaf -> 0 @@ -651,6 +696,7 @@ val sum : int tree -> int = ``` Here is how the map function can be defined in this type: + ```ocaml # let rec map f = function | Leaf -> Leaf @@ -677,6 +723,7 @@ issue - "The polymorphic variants tutorial is unreleased, so the best at this po Records are like tuples in that several values are bundled together. In a tuple, elements are identified by their position in the corresponding product type. They are either first, second, third, or at some other position. In a record, each element has a name and a value. This name-value pair is known as a field. That's why record types must be declared before being used. For instance, here is the definition of a record type meant to partially represent a Dungeons & Dragons character class. Please note that the following code is dependent upon the definitions earlier in this tutorial. Ensure you have entered the definitions in the [Enumerated Data Types](/docs/basic-data-types#enumerated-data-types) section. + ```ocaml # type character = { name : string; @@ -695,9 +742,11 @@ type character = { armor_class : int; } ``` + Values of type `character` carry the same data as inhabitants of this product: `string * int * string * character_class * character_alignment * int`. Access the fields by using the dot notation, as shown: + ```ocaml # let ghorghor_bey = { name = "Ghôrghôr Bey"; @@ -722,6 +771,7 @@ val ghorghor_bey : character = ``` To construct a new record with some field values changed without typing in the unchanged fields we can use record update syntax as shown: + ```ocaml # let togrev = { ghorghor_bey with name = "Togrev"; level = 20; armor_class = -6 };; val togrev : character = @@ -730,6 +780,7 @@ val togrev : character = ``` Note that records behave like single constructor variants. That allows pattern matching on them. + ```ocaml # match ghorghor_bey with { level; _ } -> level;; - : int = 17 @@ -740,6 +791,7 @@ Note that records behave like single constructor variants. That allows pattern m #### Type Aliases Just like values, any type can be given a name. + ```ocaml # type latitude_longitude = float * float;; type latitude_longitude = float * float @@ -750,6 +802,7 @@ This is mostly useful as a means of documentation or to shorten long type expres #### Function Parameter Aliases Function parameters can also be given a name with pattern matching for tuples and records. + ```ocaml (* Tuples as parameters *) # let tuple_sum (x, y) = x + y;; @@ -780,6 +833,7 @@ val meaning_of_life : int option -> int option = ## A Complete Example: Mathematical Expressions This example shows how to represent simple mathematical expressions like `n * (x + y)` and multiply them out symbolically to get `n * x + n * y`: + ```ocaml env=expr # type expr = | Plus of expr * expr (* a + b *) @@ -796,6 +850,7 @@ type expr = ``` The expression `n * (x + y)` would be written: + ```ocaml env=expr # let e = Times (Var "n", Plus (Var "x", Var "y"));; val e : expr = Times (Var "n", Plus (Var "x", Var "y")) @@ -803,6 +858,7 @@ val e : expr = Times (Var "n", Plus (Var "x", Var "y")) Here is a function that prints out `Times (Var "n", Plus (Var "x", Var "y"))` as something more like `n * (x + y)`: + ```ocaml env=expr # let rec to_string = function | Plus (e1, e2) -> "(" ^ to_string e1 ^ " + " ^ to_string e2 ^ ")" @@ -815,6 +871,7 @@ val to_string : expr -> string = We can write a function to multiply out expressions of the form `n * (x + y)` or `(x + y) * n`, and for this we will use a nested pattern: + ```ocaml env=expr # let rec distrib = function | Times (e1, Plus (e2, e3)) -> @@ -832,6 +889,7 @@ val distrib : expr -> expr = ``` This is how it can be used: + ```ocaml env=expr # e |> distrib |> to_string |> print_endline;; ((n * x) + (n * y)) @@ -852,6 +910,7 @@ the remaining patterns with a simple `e -> e` rule.) The reverse operation, i.e., factorising out common subexpressions, can be implemented in a similar fashion. The following version only works for the top-level expression. + ```ocaml env=expr # let top_factorise = function | Plus (Times (e1, e2), Times (e3, e4)) when e1 = e3 -> diff --git a/data/tutorials/language/0it_02_loops_and_recursion.md b/data/tutorials/language/0it_02_loops_and_recursion.md index 67ac29be8e..aed6145030 100644 --- a/data/tutorials/language/0it_02_loops_and_recursion.md +++ b/data/tutorials/language/0it_02_loops_and_recursion.md @@ -16,6 +16,7 @@ it's an example of how to write the code. OCaml supports a rather limited form of the familiar `for` loop: + ```ocaml for variable = start_value to end_value do expression @@ -25,6 +26,7 @@ for variable = start_value downto end_value do expression done ``` + A simple but real example from LablGtk: @@ -33,6 +35,7 @@ for i = 1 to n_jobs () do do_next_job () done ``` + In OCaml, `for` loops are just shorthand for writing: @@ -64,6 +67,7 @@ Line 1, characters 20-21: Warning 10 [non-unit-statement]: this expression should have type unit. - : unit = () ``` + Functional programmers tend to use recursion instead of explicit loops, and it's wise to regard **for** loops with suspicion since it can't return anything, hence OCaml's relatively powerless **for** loop. We talk about recursion @@ -77,6 +81,7 @@ while boolean-condition do expression done ``` + As with `for` loops, the language doesn't provide a way to break out of a `while` loop, except by throwing an exception, so this means that `while` loops have fairly limited use. Again, remember that functional @@ -84,7 +89,7 @@ programmers like recursion, so `while` loops are second-class citizens in OCaml. If you stop to consider `while` loops, you may see that they aren't really -any use at all, except in conjunction with our old friend *references*. +any use at all except in conjunction with our old friend *references*. Let's imagine that OCaml didn't have references for a moment: @@ -97,6 +102,7 @@ let quit_loop = false in (* how do I set quit_loop to true ?!? *) done ``` + Remember that `quit_loop` is not a real "variable." The let-binding just makes `quit_loop` shorthand for `false`. This means the `while` loop condition (shown in red) is always true, and the loop runs on @@ -123,7 +129,7 @@ If you want to loop over a list, don't be an imperative programmer and reach for your trusty six-shooter Mr. `For` Loop! OCaml has some better and faster ways to loop over lists, and they are all located in the `List` module. In fact, there are dozens of good functions in `List`, but -I'll only talk about the most useful ones here. +we'll restrict ourselves to the most useful ones in this chapter. First off, let's define a list for us to use: @@ -190,8 +196,8 @@ For operating over two lists at the same time, there are "-2" variants of some of these functions, namely `iter2`, `map2`, `for_all2`, `exists2`. -The `map` and `filter` functions operate on individual list elements in -isolation. **Fold** is a more unusual operation that is best +While `map` and `filter` functions operate on individual list elements in +isolation, **Fold** is a more unusual operation that is best thought about as "inserting an operator between each element of the list." Suppose I wanted to add all the numbers in my list together. In hand-waving terms, I want to insert a plus (+) sign between the @@ -269,7 +275,7 @@ this: ### Approach 1 Get the length of the file and read it all at once using the -`really_input` method. This is the simplest, but it might not work on +[`really_input`](https://ocaml.org/manual/api/Stdlib.html#VALreally_input) method. This is the simplest, but it might not work on channels that are not really files (e.g., reading keyboard input), which is why we have two other approaches. @@ -361,7 +367,7 @@ has a polymorphic type, so it will unify with whatever value is returned by the `with` branch. Here's the recursive version. Notice that it's *shorter* than Approach -2, but it's not so easy to understand, for imperative programmers at least: +2, but it's not so easy to understand (for imperative programmers at least): ```ocaml (* Read whole file: Approach 3 *) @@ -423,6 +429,7 @@ directory: End_of_file -> None;; val readdir_no_ex : dir_handle -> string option = ``` + The type of `readdir_no_ex` is this. Recall our earlier discussion about null pointers. @@ -560,6 +567,7 @@ let rec loop () = | base case -> [] | recursive case -> element :: loop () ``` + Compare this to our previous `range` function. The pattern of recursion is exactly the same: @@ -581,6 +589,7 @@ let rec read_directory path = else Leaf file ``` + All that remains now to make this a working program is a little bit of code to call `read_directory` and display the result: @@ -601,6 +610,7 @@ let rec loop () = | base case -> [] | recursive case -> element :: loop () ``` + The key here is actually the use of the match / base case / recursive case pattern. In this example (finding the maximum element in a list), we'll have two base cases and one recursive case. But before we @@ -651,6 +661,7 @@ Let's now code those rules above to get a working function: max x (list_max remainder);; val list_max : 'a list -> 'a = ``` + I've added comments so you can see how the rules / special cases we decided upon above really correspond to lines of code. @@ -666,6 +677,7 @@ Exception: Failure "list_max called on empty list". # list_max [5; 4; 3; 2; 1; 100];; - : int = 100 ``` + Notice how the solution proposed is both (a) very different from the imperative for-loop solution, and (b) much more closely tied to the problem specification. Functional programmers will tell you that it's @@ -686,6 +698,7 @@ Let's look at the `range` function again for about the twentieth time: else a :: range (a+1) b;; val range : int -> int -> int list = ``` + I'm going to rewrite it slightly to make something about the structure of the program clearer (still the same function however): @@ -696,6 +709,7 @@ of the program clearer (still the same function however): a :: result;; val range : int -> int -> int list = ``` + Let's call it: ```ocaml @@ -704,6 +718,7 @@ Let's call it: # List.length (range 1 1000000);; Stack overflow during evaluation (looping recursion?). ``` + Hmmm ... at first sight this looks like a problem with recursive programming, and hence with the whole of functional programming! If you write your code recursively instead of iteratively then you necessarily @@ -724,6 +739,7 @@ let rec loop () = (* do something *) loop () ``` + Because the recursive call to `loop ()` happens last, `loop` is tail-recursive and the compiler will turn the whole thing into a `while` loop. @@ -760,6 +776,7 @@ let rec range2 a b accum = else (* ... *) ``` + If `a > b` (i.e., if we've reached the end of the recursion), then stop and return the result (`accum`). @@ -773,6 +790,7 @@ tail-recursive: else range2 (a + 1) b (a :: accum);; val range2 : int -> int -> int list -> int list = ``` + There's only one slight problem with this function. It constructs the list backwards! However, this is easy to rectify by redefining range as: @@ -780,6 +798,7 @@ list backwards! However, this is easy to rectify by redefining range as: # let range a b = List.rev (range2 a b []);; val range : int -> int -> int list = ``` + It works this time, although it's a bit slow to run because it really does have to construct a list with a million elements in it: @@ -787,6 +806,7 @@ does have to construct a list with a million elements in it: # List.length (range 1 1000000);; - : int = 1000000 ``` + The following implementation is twice as fast as the previous one, because it does not need to reverse a list: @@ -799,6 +819,7 @@ val range2 : int -> int -> int list -> int list = range2 a b [];; val range : int -> int -> int list = ``` + That was a brief overview of tail recursion, but in real world situations, determining if a function is tail-recursive can be quite hard. @@ -886,6 +907,7 @@ let you: Line 1, characters 1-23: Error: The record field name is not mutable ``` + References, with which we should be familiar by now, are implemented using records with a mutable `contents` field. Check out the definition in `Stdlib`: @@ -927,6 +949,7 @@ val a : int array = [|0; 0; 0; 0; 0; 0; 0; 0; 0; 0|] # a;; - : int array = [|0; 1; 2; 3; 4; 5; 6; 7; 8; 9|] ``` + Notice the syntax for writing arrays: `[| element; element; ... |]` The OCaml compiler was designed with heavy numerical processing in mind diff --git a/data/tutorials/language/0it_04_higher_order_functions.md b/data/tutorials/language/0it_04_higher_order_functions.md index 8af2ae0f6e..c47b35e7d2 100644 --- a/data/tutorials/language/0it_04_higher_order_functions.md +++ b/data/tutorials/language/0it_04_higher_order_functions.md @@ -266,7 +266,7 @@ Sometimes it helps to apply _parts_ of a function in different orders, and somet This is what we call currying and uncurrying: * A curried `add` function will be called like `add x y`. -* An uncurried `add` functoin will be called liked `add (x, y)`. Note how this is really just one argument! +* An uncurried `add` function will be called liked `add (x, y)`. Note how this is really just one argument! Before we get to some examples, let's define some helper functions that will help us curry and uncurry functions. @@ -444,16 +444,16 @@ let c = baz (bar (foo ())) in (* ... *) ``` -But this is not so easy read sometimes, especially as the number of functions grows, as it goes from the inside out. +But this is not so easy to read sometimes, especially as the number of functions grows, as it goes from the inside out. -To avoid this we have use the `|>` operator: +To avoid this we have to use the `|>` operator: ```ocaml let c = foo () |> bar |> baz in (* ... *) ``` -This operator translates to the exact same nested calls we would've done by hand, and is really no magic. It is defined as a function: +This operator translates to the exact same nested calls we would've done by hand (there is really no magic to it). It is defined as a function: ```ocaml (* the pipeline operator *) @@ -482,6 +482,9 @@ Thanks to OCaml currying functions by default, it is practical to _partially app This is true for functions that have the most important argument in the last position (which we call **t-last**) and for functions that use labeled arguments and allow the most important argument to be passed last by passing all the names arguments first (which we usually call **t-first**). +**Note**: +The "t" in "**t-first**" and "**t-last**" stand for "**target argument**", as in "**target argument first**" and "**target argument last**". + These two cases sound very similar, but have a big practical difference when it comes to usability. Let's revisit our example above using labeled argument versions of those functions: ```ocaml @@ -514,13 +517,13 @@ We usually think of iteration when we think of looping, and going through collec But in OCaml the pattern for iteration can be extended to other kinds of data types, like optional values or results, or trees and lazy sequences. -Iterating in OCaml means that if there is a value (or more), we'd like to apply a function to it. +Iterating in OCaml means that if there is one value (or more), we'd like to apply a function to it. #### Iterating over Lists -A list in OCaml is a linked-list that is composed by a head (the first element) and a tail (the rest of the list). +A list in OCaml is a linked-list that is composed of a head (the first element) and a tail (the rest of the list). -We can iterate over lists by pattern matching on then. When doing so, we either get an empty list (`[]`), or we get a pattern with a head and a tail (`n :: rest`). On the branch with a head and a tail, we can directly use the head value and apply a function to it, and then recurse with the tail. +We can iterate over lists by pattern matching on them. When doing so, we either get an empty list (`[]`), or we get a pattern with a head and a tail (`n :: rest`). On the branch with a head and a tail we can directly use the head value and apply a function to it and then recurse with the tail. ```ocaml let rec print_nums nums = @@ -574,7 +577,7 @@ This is how `Option.iter` and `Result.iter` are defined in the standard library. #### Iterating over Maps and Sets -Larger collections of data like maps and sets, are also common in OCaml. We have dedicated modules for them but they have a _functor_ interface. This means you can't really use `Set` or `Map` directly, but you have to call the module-level function `Set.Make` to create your own custom version of the Set module for the specific types you want to store in it. +Larger collections of data like maps and sets are also common in OCaml. We have dedicated modules for them but they have a _functor_ interface. This means you can't really use `Set` or `Map` directly, but you have to call the module-level function `Set.Make` to create your own custom version of the Set module for the specific types you want to store in it. Once you create your Set or Map module, you'll find they provide functions to convert their values into lists. @@ -593,7 +596,7 @@ let iter_map map fn = iter IntMap.bindings map fn ;; let iter_set set fn = iter StringSet.elements set fn ;; ``` -You'll notice that we did not use pattern-matching this time around to iterate over the values of the Map or the Set directly. This is because the representation of Sets and Maps is private. +You'll notice that we did not use pattern-matching this time around to iterate over the values of the Map or the Set directly. This is because the representation of Sets and Maps is private. The actual implementation of iteration functions for Maps and Sets does use pattern-matching under the hood. @@ -623,7 +626,7 @@ This is almost exactly how `Seq.iter` is defined in the standard library. So far we've seen how to iterate over data types from the standard library. Now we'll see how to iterate over our own data type for trees. -We'll define our tree type to include 2 constructors. One for a leaf node, which is a node at the _end_ of the tree. The other one for nodes that have children. +We'll define our tree type to include 2 constructors. One is for a leaf node (which is a node at the _end_ of the tree), and the other is for nodes that have children. ```ocaml type 'value tree = @@ -673,7 +676,7 @@ This is called _mapping_. Mapping lists is very similar to iterating over them. We pattern match on a list, get the head of it, run a function over it, and recurse over the body. -The main difference is that instead of throwing away the resulting value from running our function over the elemnts, we will _reconstruct_ a list from it. +The main difference is that instead of throwing away the resulting value from running our function over the elements, we will _reconstruct_ a list from it. ```ocaml let rec map list fn = @@ -788,7 +791,7 @@ let rec fold_tree tree fn acc = ;; ``` -And voila! Our function now types correctly and we can use it to reduce our trees down to any value. +And voila! Our function now type-checks correctly and we can use it to reduce our trees down to any value. ### Sorting @@ -820,6 +823,7 @@ Most OCaml modules include a `compare` function that can be pass in to `sort`: ```ocaml let int_array = [|3;0;100|];; + Array.sort Int.compare int_array;; List.sort String.compare ["z";"b";"a"];; @@ -831,7 +835,7 @@ List.sort Bool.compare [true;false;false];; One last common higher-order pattern in functional programming is the ability to _join_ data from within. For historical reasons, this is normally called a _bind_. -For example, if we have a list, and map over it with a function that returns a list, then we'll have a list of lists. Sometimes we want this, but some times we would rather the new list was _flattened_ instead of _nested_. +For example, if we have a list and we map over it with a function that returns a list, then we'll have a list of lists. Sometimes we want this, but sometimes we would rather the new list was _flattened_ instead of _nested_. To do this with lists we can use the `concat_map` function, which looks like this: diff --git a/data/tutorials/language/0it_05_labels.md b/data/tutorials/language/0it_05_labels.md index 77d1876116..7218e02a79 100644 --- a/data/tutorials/language/0it_05_labels.md +++ b/data/tutorials/language/0it_05_labels.md @@ -15,12 +15,14 @@ Throughout this tutorial, the code is written in UTop. In this document paramete ## Passing Labelled Arguments The function `Option.value` from the standard library has a parameter labelled `default`. + ```ocaml # Option.value;; - : 'a option -> default:'a -> 'a = ``` Labelled arguments are passed using a tilde `~` and can be placed at any position and in any order. + ```ocaml # Option.value (Some 10) ~default:42;; - : int = 10 @@ -42,6 +44,7 @@ Error: Syntax error ## Labelling Parameters Here is how to name parameters in a function definition: + ```ocaml # let rec range ~first:lo ~last:hi = if lo > hi then [] @@ -54,6 +57,7 @@ The parameters of `range` are named - `first` and `last` when calling the function; these are the labels. Here is how `range` is used: + ```ocaml # range ~first:1 ~last:10;; - : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] @@ -63,6 +67,7 @@ Here is how `range` is used: ``` It is possible to use a shorter syntax when using the same name as label and parameter. + ```ocaml # let rec range ~first ~last = if first > last then [] @@ -75,6 +80,7 @@ At parameter definition `~first` is the same as `~first:first`. Passing argument ## Passing Optional Arguments Optional arguments can be omitted. When passed, a tilde `~` or a question mark `?` must be used. They can be placed at any position and in any order. + ```ocaml # let sum ?(init=0) u = List.fold_left ( + ) init u;; val sum : ?init:int -> int list -> int = @@ -87,6 +93,7 @@ val sum : ?init:int -> int list -> int = ``` It is also possible to pass optional arguments as values of type `option`. This is done using a question mark when passing the argument. + ```ocaml # sum [0; 1; 2; 3; 4; 5] ?init:(Some 100);; - : int = 115 @@ -98,6 +105,7 @@ It is also possible to pass optional arguments as values of type `option`. This ## Defining Optional Parameters With Default Values In the previous section, we've defined a function with an optional parameter without explaining how it works. Let's look at a different variant of this function: + ```ocaml # let sum ?init:(x=0) u = List.fold_left ( + ) x u;; val sum : ?init:int -> int list -> int = @@ -128,6 +136,7 @@ val get_ok : ?exn:('a -> exn) -> ('b, 'a) result -> 'b = An optional parameter can be declared without specifying a default value. + ```ocaml # let sub ?(pos=0) ?len:len_opt s = let default = String.length s - pos in @@ -146,6 +155,7 @@ When an optional parameter isn't given a default value, its type inside the func This enables the following usages: + ```ocaml # sub ~len:5 ~pos:2 "immutability";; - : string = "mutab" @@ -161,6 +171,7 @@ This enables the following usages: ``` It is possible to use the same name for the `len` parameter and label name. + ```ocaml # let sub ?(pos=0) ?len s = let default = String.length s - pos in @@ -174,6 +185,7 @@ val sub : ?pos:int -> ?len:int -> string -> string = Let's compare two possible variants of the `String.concat` function from the standard library which has type `string -> string list -> string`. In the first version, the optional separator is the last declared parameter. + ```ocaml # let concat_warn ss ?(sep="") = String.concat sep ss;; Line 1, characters 15-18: @@ -192,6 +204,7 @@ val concat_warn : string list -> ?sep:string -> string = ``` In the second version, the optional separator is the first declared parameter. + ```ocaml # let concat ?(sep="") ss = String.concat sep ss;; val concat : ?sep:string -> string list -> string = @@ -232,6 +245,7 @@ val range : int -> first:int -> last:int -> int list = ## Function with Only Optional Arguments When all parameters of a function need to be optional, a dummy, positional and occurring last parameter must be added. The unit `()` value comes in handy for this. This is what is done here. + ```ocaml # let hello ?(who="world") () = "hello, " ^ who;; val hello : ?who:string -> string = @@ -260,6 +274,7 @@ Without the unit parameter, the `optional argument cannot be erased` warning wou ## Forwarding an Optional Argument Passing an optional argument with a question mark sign `?` allows forwarding it without unwrapping. These examples reuse the `sub` function defined in the [Optional Arguments Without Default Values](#optional-arguments-without-default-values) section. + ```ocaml # let take ?len s = sub ?len s;; val take : ?len:int -> string -> string = diff --git a/data/tutorials/language/0it_06_imperative.md b/data/tutorials/language/0it_06_imperative.md index 14e2e04487..30b77c12a0 100644 --- a/data/tutorials/language/0it_06_imperative.md +++ b/data/tutorials/language/0it_06_imperative.md @@ -40,6 +40,7 @@ In the following sections, we introduce OCaml's language features for dealing wi ## References There is a special kind of value, called _reference_, whose contents can be updated: + ```ocaml # let d = ref 0;; val d : int ref = {contents = 0} @@ -79,6 +80,7 @@ The update takes place as a [side effect](https://en.wikipedia.org/wiki/Side_eff # ( ! );; - : 'a ref -> 'a = ``` + The dereference operator is a function that takes a reference and returns its contents. Refer to the [Operators](/docs/operators) documentation for more information on how unary and binary operators work in OCaml. @@ -90,6 +92,7 @@ When working with mutable data in OCaml, ## Mutable Record Fields Any field in a record can be tagged using the `mutable` keyword. Such a field can be updated. + ```ocaml # type book = { series : string; @@ -112,6 +115,7 @@ For instance, here is how a bookshop could track its inventory: * Field `stock` is mutable because this value changes with each sale or restocking. Such a database should have an entry like this: + ```ocaml # let vol_7 = { series = "Murderbot Diaries"; @@ -126,6 +130,7 @@ val vol_7 : book = ``` When the bookshop receives a delivery of 10 of these books, we update the mutable `stock` field: + ```ocaml # vol_7.stock <- vol_7.stock + 10;; - : unit = () @@ -142,9 +147,12 @@ Mutable record fields are updated using the left arrow symbol `<-`. In the expre In contrast to references, there is no special syntax to dereference a mutable record field. +**Remark**: the left arrow symbol `<-` for mutating mutable record field values is not an operator function, like the assignment operator `( := )` is for `refs`. It is rather a _construct_ of the language, it has no type. + ### Remark: References Are Single Field Records In OCaml, references are records with a single mutable field: + ```ocaml # #show_type ref;; type 'a ref = { mutable contents : 'a; } @@ -153,6 +161,7 @@ type 'a ref = { mutable contents : 'a; } The type `'a ref` is a record with a single field `contents`, which is marked with the `mutable` keyword. Since references are single field records, we can define functions `create`, `assign`, and `deref` using the mutable record field update syntax: + ```ocaml # let create v = { contents = v };; val create : 'a -> 'a ref = @@ -184,6 +193,7 @@ The functions: ## Arrays In OCaml, an array is a mutable, fixed-size data structure that can store a sequence of elements of the same type. Arrays are indexed by integers, provide constant-time access, and allow the update of elements. + ```ocaml # let g = [| 2; 3; 4; 5; 6; 7; 8 |];; val g : int array = [|2; 3; 4; 5; 6; 7; 8|] @@ -207,6 +217,7 @@ For a more detailed discussion on arrays, see the [Arrays](/docs/arrays) tutoria ## Byte Sequences The `bytes` type in OCaml represents a fixed-length, mutable byte sequence. In a value of type `bytes`, each element has 8 bits. Since characters in OCaml are represented using 8 bits, `bytes` values are mutable `char` sequences. Like arrays, byte sequences support indexed access. + ```ocaml # let h = Bytes.of_string "abcdefghijklmnopqrstuvwxyz";; val h : bytes = Bytes.of_string "abcdefghijklmnopqrstuvwxyz" @@ -251,6 +262,7 @@ These attributes need to be set correctly (i.e., turn off echoing and disable ca We read characters from standard input using the `input_char` function from the OCaml standard library. Below is the first implementation. If you're working in macOS, run `#require "unix";;` first to avoid an `Unbound module error`. + ```ocaml # let get_char () = let open Unix in @@ -272,6 +284,7 @@ In this implementation, we update the fields of `termio` * after `input_char`, restoring the initial values. Here is the second implementation: + ```ocaml # let get_char () = let open Unix in @@ -321,9 +334,11 @@ Hello, world! - : int = 42 ``` + In this example, the first two expressions are `print_endline` function calls, which produce side effects (printing to the console), and the last expression is simply the integer `42`, which becomes the value of the entire sequence. The `;` operator is used to separate these expressions. **Remark** Even though it's called the sequence operator, the semicolon is not truly an operator because it is not a function of type `unit -> 'a -> 'a`. It is rather a _construct_ of the language. It allows adding a semicolon at the end of a sequence expression. + ```ocaml # (); 42; ;; - : int = 42 @@ -340,18 +355,20 @@ Imagine we want to write a function that: 2. Updates the reference's contents to _2 × (n + 1)_ This is arguably convoluted and does not work: + ```ocaml # let f r = r := incr r; 2 * !r;; Error: This expression has type unit but an expression was expected of type int ``` But here is how it can be made to work: + ```ocaml # let f r = r := begin incr r; 2 * !r end;; val f : int ref -> unit = ``` -The error came from assign `:=`, which associates stronger than a semicolon `;`. Here is what we want to do, in order: +The error came from the assign operator `:=`, which associates stronger than a semicolon `;`. Here is what we want to do, in order: 1. Increment `r` 2. Compute `2 * !r` 3. Assign into `r` @@ -359,6 +376,7 @@ The error came from assign `:=`, which associates stronger than a semicolon `;`. Remember the value of a semicolon-separated sequence is the value of its last expression. Grouping the first two steps with `begin … end` fixes the error. **Fun fact**: `begin … end` and parentheses are literally the same: + ```ocaml # begin end;; - : unit = () @@ -367,12 +385,14 @@ Remember the value of a semicolon-separated sequence is the value of its last ex ### `if … then … else …` and Side Effects In OCaml, `if … then … else …` is an expression. + ```ocaml # 6 * if "foo" = "bar" then 5 else 5 + 2;; - : int = 42 ``` A conditional expression return type can be `unit` if both branches are too. + ```ocaml # if 0 = 1 then print_endline "foo" else print_endline "bar";; bar @@ -380,6 +400,7 @@ bar ``` The above can also be expressed this way: + ```ocaml # print_endline (if 0 = 1 then "foo" else "bar");; bar @@ -387,18 +408,21 @@ bar ``` The `unit` value `()` can serve as a [no-op](https://en.wikipedia.org/wiki/Noop) when only one branch has something to execute. + ```ocaml # if 0 = 1 then print_endline "foo" else ();; - : unit = () ``` But OCaml also allows writing `if … then … ` expressions without an `else` branch, which is the same as the above. + ```ocaml # if 0 = 1 then print_endline "foo";; - : unit = () ``` In parsing, conditional expressions groups more than sequencing: + ```ocaml # if true then print_endline "A" else print_endline "B"; print_endline "C";; A @@ -409,7 +433,8 @@ C Here `; print_endline "C"` is executed after the whole conditional expression, not after `print_endline "B"`. If you want to have two prints in a conditional expression branch, use `begin … end`. - ```ocaml + +```ocaml # if true then print_endline "A" else begin @@ -421,6 +446,7 @@ A ``` Here is an error you might encounter: + ```ocaml # if true then print_endline "A"; @@ -435,6 +461,7 @@ Failing to group in the first branch results in a syntax error. What's before th ### For Loop A `for` loop is an expression of type `unit`. Here, `for`, `to`, `do`, and `done` are keywords. + ```ocaml # for i = 0 to 5 do Printf.printf "%i\n" i done;; 0 @@ -455,6 +482,7 @@ Here: The iteration evaluates the body expression (which may contain `i`) until `i` reaches `5`. The body of a `for` loop must be an expression of type `unit`: + ```ocaml # let j = [| 2; 3; 4; 5; 6; 7; 8 |];; val j : int array = [|2; 3; 4; 5; 6; 7; 8|] @@ -468,6 +496,7 @@ Warning 10 [non-unit-statement]: this expression should have type unit. When you use the `downto` keyword (instead of the `to` keyword), the counter decreases on every iteration of the loop. `for` loops are convenient to iterate over and modify arrays: + ```ocaml # let sum = ref 0 in for i = 0 to Array.length j - 1 do sum := !sum + j.(i) done; @@ -476,6 +505,7 @@ When you use the `downto` keyword (instead of the `to` keyword), the counter dec ``` **Note:** Here is how to do the same thing using an iterator function: + ```ocaml # let sum = ref 0 in Array.iter (fun i -> sum := !sum + i) j; !sum;; - : int = 35 @@ -484,6 +514,7 @@ When you use the `downto` keyword (instead of the `to` keyword), the counter dec ### While Loop A `while` loop is an expression of type `unit`. Here, `while`, `do`, and `done` are keywords. + ```ocaml # let i = ref 0 in while !i <= 5 do @@ -512,6 +543,7 @@ In this example, the `while` loop continues to execute as long as the value held Throwing the `Exit` exception is a recommended way to immediately exit from a loop. The following example uses the `get_char` function we defined earlier (in the section [Example: `get_char` Function](#example-get_char-function)). + ```ocaml # try print_endline "Press Escape to exit"; @@ -528,15 +560,16 @@ This `while` loop echoes characters typed on the keyboard. When the ASCII `Escap ### References Inside Closures -In the following example, the function `create_counter` returns a closure that hides a mutable reference `n`. This closure captures the environment where `n` is defined and can modify `n` each time it's invoked. The `n` reference is "hidden" within the closure, encapsulating its state. +In the following example, the function `create_counter` returns a closure that “hides” a mutable reference `counter`. This closure captures the environment where `counter` is defined and can modify `counter` each time it's invoked. The `counter` reference is “hidden” within the closure, encapsulating its state. ```ocaml # let create_counter () = - let n = ref 0 in - fun () -> incr n; !n;; + let counter = ref (-1) in + fun () -> incr counter; !counter;; val create_counter : unit -> unit -> int = ``` -First, we define a function named `create_counter` that takes no arguments. Inside `create_counter`, a reference `n` is initialised with the value 0. This reference will hold the state of the counter. Next, we define a closure that takes no arguments (fun () ->). The closure increments the value of `n` (the counter) using `incr n`, then returns the current value of `n` using `!n`. + +First, we define a function named `create_counter` that takes no arguments. Inside `create_counter`, a reference `counter` is initialised with the value -1. This reference will hold the state of the counter. Next, we define a closure that takes no arguments `(fun () ->)`. The closure increments `counter` using `incr counter`, then returns the current value of `counter` using `!counter`. ```ocaml # let c1 = create_counter ();; @@ -545,24 +578,26 @@ val c1 : unit -> int = # let c2 = create_counter ();; val c2 : unit -> int = ``` -Now, we shall create a closure `c1` that encapsulates a counter. Calling `c1 ()` will increment the counter associated with `c1` and return its current value. Similarly, we create another closure `c2` with its own independent counter. + +Now, using partial application, we create two closure `c1` and `c2` that encapsulates a counter. Calling `c1 ()` will increment the counter associated with `c1` and return its current value. Similarly, calling `c2 ()` will update its own independent counter. ```ocaml # c1 ();; -- : int = 1 +- : int = 0 # c1 ();; -- : int = 2 +- : int = 1 # c2 ();; -- : int = 1 +- : int = 0 # c1 ();; -- : int = 3 +- : int = 2 ``` -Calling `c1 ()` increments the counter associated with `c1` and returns its current value. Since this is the first call, the counter starts at 1. Another call to `c1 ()` increments the counter again, so it returns 2. -Calling `c2 ()` increments the counter associated with `c2`. Since `c2` has its own independent counter, it starts at 1. Another call to `c1 ()` increments its counter, resulting in 3. +Calling `c1 ()` increments the counter associated with `c1` and returns its current value. Since this is the first call, the counter starts at 0. Another call to `c1 ()` increments the counter again, so it returns 1. + +Calling `c2 ()` increments the counter associated with `c2`. Since `c2` has its own independent counter, it starts at 0. Another call to `c1 ()` increments its counter, resulting in 2. ## Recommendations for Mutable State and Side Effects @@ -571,6 +606,7 @@ Functional and imperative programming styles are often used together. However, n ### Good: Function-Encapsulated Mutability Here is a function that computes the sum of an array of integers. + ```ocaml # let sum m = let result = ref 0 in @@ -592,6 +628,7 @@ Some applications maintain some state while they are running. Here are a couple - A cache. The following is a toy line editor, using the `get_char` function [defined earlier](#example-getchar-function). It waits for characters on standard input and exits on end-of-file, carriage return, or newline. Otherwise, if the character is printable, it prints it and records it in a mutable list used as a stack. If the character is the delete code, the stack is popped and the last printed character is erased. + ```ocaml # let record_char state c = (String.make 1 c, c :: state);; @@ -635,6 +672,7 @@ This is a possible way to handle an application-wide state. As in the [Function- ### Good: Precomputing Values Let's imagine you store angles as fractions of the circle in 8-bit unsigned integers, storing them as `char` values. In this system, 64 is 90 degrees, 128 is 180 degrees, 192 is 270 degrees, 256 is full circle, and so on. If you need to compute cosine on those values, an implementation might look like this: + ```ocaml # let char_cos c = c |> int_of_char |> float_of_int |> ( *. ) (Float.pi /. 128.0) |> cos;; @@ -642,6 +680,7 @@ val char_cos : char -> float = ``` However, it is possible to make a faster implementation by precomputing all the possible values in advance. There are only 256 of them, which you'll see listed after the first result below: + ```ocaml # let char_cos_tab = Array.init 256 (fun i -> i |> char_of_int |> char_cos);; val char_cos_tab : float array = @@ -658,9 +697,7 @@ However, instead of precomputing everything, memoization uses a cache that is po * are found in the cache (it is a hit) and the stored result is returned, or they * are not found in the cache (it's a miss), and the result is computed, stored in the cache, and returned. -You can find a concrete example of memoization and a more in-depth explanation in the chapter on [Memoization](https://cs3110.github.io/textbook/chapters/ds/memoization.html) of "OCaml Programming: Correct + Efficient + Beautiful." - - +You can find a concrete example of memoization and an in-depth explanation in the chapter on [Memoization](https://ocaml.org/docs/memoization) of "OCaml Programming: Correct + Efficient + Beautiful." ### Good: Functional by Default @@ -668,16 +705,17 @@ By default, OCaml programs should be written in a mostly functional style. This It is possible to use an imperative programming style without losing the benefits of type and memory safety. However, it doesn't usually make sense to only program in an imperative style. Not using functional programming idioms at all would result in non-idiomatic OCaml code. -Most existing modules provide an interface meant to be used in a functional way. Some would require the development and maintenance of [wrapper libraries](https://en.wikipedia.org/wiki/Wrapper_library) to be used in an imperative setting and such use would in many cases be inefficient. +Most existing modules provide an interface meant to be used in a functional way. Some require the development and maintenance of [wrapper libraries](https://en.wikipedia.org/wiki/Wrapper_library) to be used in an imperative setting and such use results in inefficient code. ### It Depends: Module State A module may expose or encapsulate a state in several different ways: 1. Good: expose a type representing a state, with state creation or reset functions -1. It depends: only expose state initialisation, which implies there only is a single state +1. It depends: only expose state initialisation, which implies there is only a single state 1. Bad: mutable state with no explicit initialisation function or no name referring to the mutable state For example, the [`Hashtbl`](/manual/api/Hashtbl.html) module provides an interface of the first kind. It has the type `Hashtbl.t` representing mutable data. It also exposes `create`, `clear`, and `reset` functions. The `clear` and `reset` functions return `unit`. This strongly signals the reader that they perform the side-effect of updating the mutable data. + ```ocaml # #show Hashtbl.t;; type ('a, 'b) t = ('a, 'b) Hashtbl.t @@ -696,7 +734,10 @@ On the other hand, a module may define mutable data internally impacting its beh ### Bad: Undocumented Mutation +**Note**: The following example code will purposely not run in your REPL; the function `Array.truncate` is not defined. It is provided as an example to contemplate and avoid. + Here's an example of bad code: + ```ocaml # let partition p k = let m = Array.copy k in @@ -715,7 +756,6 @@ Here's an example of bad code: Error: Unbound value Array.truncate ``` -**Note:** This example will not run in the REPL, since the function `Array.truncate` is not defined. To understand why this is bad code, assume that the function `Array.truncate` has type `int -> 'a array -> 'a array`. It behaves such that `Array.truncate 3 [5; 6; 7; 8; 9]` returns `[5; 6; 7]`, and the returned array physically corresponds to the 3 first cells of the input array. @@ -739,6 +779,9 @@ GOTCHA: This is the dual of the previous anti-pattern. “Mutable in disguise” ### Bad: Undocumented Side Effects Consider this code: + +**Note**: The following example will not run in your REPL; there is no module `Analytics` defined. It is provided as an example to contemplate. [Analytics](https://en.wikipedia.org/wiki/Web_analytics) are remote monitoring libraries. + ```ocaml # module Array = struct include Stdlib.Array @@ -749,8 +792,6 @@ Consider this code: Error: Unbound module Analytics ``` -**Note:** This code will not run because there is no module called `Analytics`. [Analytics](https://en.wikipedia.org/wiki/Web_analytics) are remote monitoring libraries. - A module called `Array` is defined; it shadows and includes the [`Stdlib.Array`](/manual/api/Array.html) module. See the [Module Inclusion](docs/modules#module-inclusion) part of the [Modules](docs/modules) tutorial for details about this pattern. To understand why this code is bad, figure out that `Analytics.collect` is a function that makes a network connection to transmit data to a remote server. @@ -762,6 +803,7 @@ If you're writing functions with non-obvious side effects, don't shadow existing ### Bad: Side Effects Depending on Order of Evaluation Consider the following code: + ```ocaml # let id_print s = print_string (s ^ " "); s;; val id_print : string -> string = @@ -781,6 +823,7 @@ In the second line, we apply `id_print` to the arguments `"Monday"`, `"Tuesday"` Since the evaluation order for function arguments in OCaml is not explicitly defined, the order in which the `id_print` side effects take place is unreliable. In this example, the arguments are evaluated from right to left, but this could change in future compiler releases. This issue also arises when applying arguments to variant constructors, building tuple values, or initialising record fields. Here, it is illustrated on a tuple value: + ```ocaml # let r = ref 0 in ((incr r; !r), (decr r; !r));; - : int * int = (0, -1) @@ -788,10 +831,11 @@ This issue also arises when applying arguments to variant constructors, building The value of this expression depends on the order of subexpression evaluation. Since this order is not specified, there is no reliable way to know what this value is. At the time of writing this tutorial, the evaluation produced `(0, -1)`, but if you see something else, it is not a bug. Such an unreliable value must a avoided. -To ensure that evaluation takes place in a specific order, use the means to put expressions in sequences. Check the [Evaluating Expressions in Sequence](#evaluating-expressions-in-sequence) section. +To ensure that evaluation takes place in a specific order, use the means to put expressions in sequences using either `let … in` expressions or the semi-colon sequence operator (`;`). Check the [Evaluating Expressions in Sequence](#evaluating-expressions-in-sequence) section. ```ocaml let hello () = print_endline "Hello from Athens" ``` Here is the file `berlin.ml`: + ```ocaml let () = Athens.hello () @@ -43,17 +45,21 @@ let () = Athens.hello () To compile them using [Dune](https://dune.build/), at least two configuration files are required: * The `dune-project` file contains project-wide configuration. + ```lisp (lang dune 3.7) ``` + * The `dune` file contains actual build directives. A project may have several `dune` files, one per directory containing things to build. This single line is sufficient in this example: + ```lisp (executable (name berlin)) ``` After you create those files, build and run them: + ```bash $ opam exec -- dune build @@ -88,6 +94,7 @@ anything the module provides. If you are using a module heavily, you might want to `open` it. This brings the module's definitions into scope. In our example, `berlin.ml` could have been written: + ```ocaml open Athens @@ -98,6 +105,7 @@ Using `open` is optional. Usually, we don't open a module like `List` because it provides names other modules also provide, such as [`Array`](/manual/api/Array.html) or `Option`. Modules like `Printf` provide names that aren't subject to conflicts, such as `printf`. Placing `open Printf` at the top of a file avoids writing `Printf.printf` repeatedly. + ```ocaml open Printf let data = ["a"; "beautiful"; "day"] @@ -110,6 +118,7 @@ let () = List.iter (printf "%s\n") data at the top of every file. Refer to Dune documentation if you need to opt-out. You can open a module inside a definition, using the `let open ... in` construct: + ```ocaml # let list_sum_sq m = let open List in @@ -118,6 +127,7 @@ val list_sum_sq : int -> int = ``` The module access notation can be applied to an entire expression: + ```ocaml # let array_sum_sq m = Array.(init m Fun.id |> map (fun i -> i * i) |> fold_left ( + ) 0);; @@ -139,6 +149,7 @@ interface. By default, when no corresponding `.mli` file is provided, an implementation has a default interface where everything is public. Copy the `athens.ml` file into `cairo.ml` and change its contents: + ```ocaml let message = "Hello from Cairo" @@ -146,6 +157,7 @@ let hello () = print_endline message ``` As it is, `Cairo` has the following interface: + ```ocaml val message : string @@ -158,6 +170,7 @@ acts as a mask over the module's implementation. The `cairo.ml` file defines Filenames without extensions must be the same. To turn `message` into a private definition, don't list it in the `cairo.mli` file: + ```ocaml val hello : unit -> unit @@ -178,11 +191,13 @@ let () = Cairo.hello () Update the `dune` file to allow this example's compilation aside from the previous one. + ```lisp (executables (names berlin delhi)) ``` Compile and execute both programs: + ```shell $ opam exec -- dune exec ./berlin.exe Hello from Athens @@ -192,6 +207,7 @@ Hello from Cairo ``` You can check that `Cairo.message` is not public by attempting to compile a `delhi.ml` file containing: + ```ocaml let () = print_endline Cairo.message ``` @@ -239,12 +255,14 @@ let dalet_of = function ``` Update file `dune` to have three targets; two executables: `berlin` and `delhi`; and a library `exeter`. + ```lisp (executables (names berlin delhi) (modules athens berlin cairo delhi)) (library (name exeter) (modules exeter)) ``` Run the `opam exec -- dune utop` command. This triggers `Exeter`'s compilation, launches `utop`, and loads `Exeter`. + ```ocaml # open Exeter;; @@ -253,12 +271,14 @@ type aleph = Ada | Alan | Alonzo ``` Type `aleph` is public. Values can be created or accessed. + ```ocaml # #show bet;; Unknown element. ``` Type `bet` is private. It is not available outside of the implementation where it is defined, here `Exeter`. + ```ocaml # #show gimel;; type gimel @@ -277,6 +297,7 @@ val gimel_of_bool : bool -> gimel ``` Type `gimel` is _abstract_. Values can be created or manipulated, but only as function results or arguments. Just the provided functions `gimel_of_bool`, `gimel_flip`, and `gimel_to_string` or polymorphic functions can receive or return `gimel` values. + ```ocaml # #show dalet;; type dalet = private Dennis of int | Donald of string | Dorothy @@ -337,6 +358,7 @@ executable: To define a submodule's interface, we can provide a _module signature_. This is done in this second version of the `florence.ml` file: + ```ocaml module Hello : sig val print : unit -> unit @@ -353,6 +375,7 @@ The first version made `Florence.Hello.message` public. In this version it can't ### Module Signatures are Types The role played by module signatures to implementations is akin to the role played by types to values. Here is a third possible way to write file `florence.ml`: + ```ocaml module type HelloType = sig val print : unit -> unit @@ -389,6 +412,7 @@ module Unit : ``` The OCaml compiler tool chain can be used to dump an `.ml` file's default interface. + ```shell $ ocamlc -i cairo.ml val message : string @@ -423,6 +447,7 @@ module from another `.ml` file, we need to add `open Extlib` at the beginning. ## Stateful Modules A module may have an internal state. This is the case for the `Random` module from the standard library. The functions `Random.get_state` and `Random.set_state` provide read and write access to the internal state, which is nameless and has an abstract type. + ```ocaml # let s = Random.get_state ();; val s : Random.State.t = diff --git a/data/tutorials/language/1ms_01_functors.md b/data/tutorials/language/1ms_01_functors.md index 16dffbcedf..9cceaf187a 100644 --- a/data/tutorials/language/1ms_01_functors.md +++ b/data/tutorials/language/1ms_01_functors.md @@ -12,7 +12,7 @@ prerequisite_tutorials: In this tutorial, we look at how to apply functors and how to write functors. We also show some use cases involving functors. -As suggested by the name, a _functor_ is almost like a function. However, while functions are between values, functors are between modules. A functor has a module as a parameter and returns a module as a result. A functor in OCaml is a parametrised module, not to be confused with a [functor in mathematics](https://en.wikipedia.org/wiki/Functor). +As suggested by the name, a _functor_ is almost like a function. However, while the inputs and outputs of functions are values, functors are between modules. A functor has a module as a parameter and returns a module as a result. A functor in OCaml is a parametrised module, not to be confused with a [functor in mathematics](https://en.wikipedia.org/wiki/Functor). **Note**: The files illustrating this tutorial are available as a [Git repo](https://github.com/ocaml-web/ocamlorg-docs-functors). @@ -25,12 +25,14 @@ $ mkdir funkt; cd funkt ``` Place the following in the file **`dune-project`**: + ```lisp (lang dune 3.7) (package (name funkt)) ``` The content of the file **`dune`** should be this: + ```lisp (executable (name funkt) @@ -47,6 +49,7 @@ Check that this works using the `opam exec -- dune exec funkt` command. It shoul The standard library contains a [`Set`](/manual/api/Set.html) module which is designed to handle sets. This module enables you to perform operations such as union, intersection, and difference on sets. You may check the [Set](/docs/sets) tutorial to learn more about this module, but it is not required to follow the present tutorial. To create a set module for a given element type (which allows you to use the provided type and its associated [functions](/manual/api/Set.S.html)), it's necessary to use the functor `Set.Make` provided by the `Set` module. Here is a simplified version of `Set`'s interface: + ```ocaml module type OrderedType = sig type t @@ -67,7 +70,6 @@ Here is how this reads (starting from the bottom, then going up): Here is an example of how to use `Set.Make`: **`funkt.ml`** - ```ocaml module StringCompare = struct type t = string @@ -86,11 +88,13 @@ This defines a module `Funkt.StringSet`. What `Set.Make` needs are: another type, here `string`. If that other type is also called `t`, the compiler will trigger an error _“The type abbreviation t is cyclic”_. This can be worked around by adding the `nonrec` keyword to the type definition, like this: + ```ocaml type nonrec t = t ``` This can be simplified using an _anonymous module_ expression: + ```ocaml module StringSet = Set.Make(struct type t = string @@ -105,6 +109,7 @@ However, since the module `String` already defines - Function `compare` of type `t -> t -> bool` compares two strings This can be simplified even further into this: + ```ocaml module StringSet = Set.Make(String) ``` @@ -178,6 +183,7 @@ That's the case for the sets, maps, and hash tables provided by the standard lib * The functor returns a module that implements what is promised, as described by the result interface Here is the module's signature that the functors `Set.Make` and `Map.Make` expect: + ```ocaml module type OrderedType = sig type t @@ -186,6 +192,7 @@ end ``` Here is the module's signature that the functor `Hashtbl.Make` expects: + ```ocaml module type HashedType = sig type t @@ -208,6 +215,7 @@ There are many kinds of [heap](https://en.wikipedia.org/wiki/Heap_(data_structur The kind of data structures and algorithms used to implement a heap is not discussed in this document. The common prerequisite to implement any heap is a means to compare the elements they contain. That's the same signature as the parameter of `Set.Make` and `Map.Make`: + ```ocaml module type OrderedType = sig type t @@ -216,6 +224,7 @@ end ``` Using such a parameter, a heap implementation must provide at least this interface: + ```ocaml module type HeapType = sig type elt @@ -321,7 +330,7 @@ Check the program's behaviour using `opam exec -- dune exec funkt < dune`. [Dependency injection](https://en.wikipedia.org/wiki/Dependency_injection) is a way to parametrise over a dependency. -Here is a refactoring of the module `IterPrint` to use this technique: +Here is a refactoring of the module `IterPrint` to use dependency injection: **`iterPrint.ml`** ```ocaml @@ -340,12 +349,11 @@ module Make(Dep: Iterable) : S with type 'a t := 'a Dep.t = struct end ``` -The module `IterPrint` is refactored into a functor that takes a module providing the function `iter` as a parameter. The `with type 'a t := 'a Dep.t` constraint means the type `t` from the parameter `Dep` replaces the type `t` in the result module. This allows `f`'s type to use `Dep`'s `t` type. With this refactoring, `IterPrint` only has one dependency. At its compilation time, no implementation of function `iter` is available yet. +The module `IterPrint` is refactored into a functor that takes a module providing the function `iter` as a parameter. The `with type 'a t := 'a Dep.t` is called a "destructive type substitution", and it is a constraint that means the type `t` from the parameter `Dep` replaces the type `t` in the result module. This allows `f`'s type to use `Dep`'s `t` type. With this refactoring, `IterPrint` only has one dependency. At its compilation time, no implementation of function `iter` is available yet. -**Note**: An OCaml interface file (`.mli`) must be a module, not a functor. Functors must be embedded inside modules. Therefore, it is customary to call them `Make`. +**Note**: An OCaml file (`.ml`) defines a module, not a functor. Functors must be embedded inside modules. It is customary to call the functor `Make`. This allows writing `module IntSet = Set.Make(Int)`. **`funkt.ml`** - ```ocaml module StringSet = Set.Make(String) module IterPrint = IterPrint.Make(List) @@ -425,7 +433,9 @@ module Make(Dep: Iterable) : S with type 'a t := 'a Dep.t = struct end ``` -In the example above, `t` from `with type` takes precedence over the local `t`, which only has a local scope. Don't shadow names too often because it makes the code harder to understand. +In the example above, `t` from `with type` takes precedence over the local `t`, which only has a local scope. + +**Warning**: Don't shadow names too often because it makes the code harder to understand. ## Write a Functor to Extend Modules @@ -496,11 +506,11 @@ Modules can hold a state. Functors can provide a means to initialise stateful mo **`random.ml`** ```ocaml -module type SeedType : sig +module type SeedType = sig val v : int array end -module type S : sig +module type S = sig val reset_state : unit -> unit val bits : unit -> int @@ -535,6 +545,7 @@ end ``` Create this file and launch `utop`. + ```ocaml # #mod_use "random.ml";; diff --git a/data/tutorials/language/1ms_02_dune.md b/data/tutorials/language/1ms_02_dune.md index a5e56f692e..586679e9e0 100644 --- a/data/tutorials/language/1ms_02_dune.md +++ b/data/tutorials/language/1ms_02_dune.md @@ -15,9 +15,16 @@ Dune provides several means to arrange modules into libraries. We look at Dune's This tutorial uses the [Dune](https://dune.build) build tool. Make sure you have version 3.7 or later installed. +In the following toy project, we create an OCaml library for the World Meteorological Organization, with clouds as its subject. + +We use unique terms for different elements of our project to avoid ambiguity. For instance, the directory containing the file `cloud.ml` isn't named `cloud`. A different term is used. We also use the Spanish word "nube" and the [Nahuatl](https://en.wikipedia.org/wiki/Nahuatl) word "mixtli," where both terms mean "cloud." + +**Note**: The other terms we use are classifications of clouds. These include "[cumulus](https://en.wikipedia.org/wiki/Cumulus_cloud)" (fluffy), "[nimbus](https://en.wiktionary.org/wiki/nimbus)" (precipitating), "[cumulonimbus](https://en.wikipedia.org/wiki/Cumulonimbus_cloud)" (fluffy and precipitating), "[nimbostratus](https://en.wikipedia.org/wiki/Nimbostratus_cloud)" (flat, amorphous and precipitating), and "[altocumulus](https://en.wikipedia.org/wiki/Altocumulus_cloud)" (high altitude and fluffy). + ## Minimum Project Setup This section details the structure of an almost-minimum Dune project setup. Check [Your First OCaml Program](/docs/your-first-program) for automatic setup using the `dune init proj` command. + ```shell $ mkdir mixtli; cd mixtli ``` @@ -62,6 +69,7 @@ let () = ``` Here is the resulting output: + ```shell $ opam exec -- dune exec nube Nimbostratus (Ns) @@ -70,6 +78,7 @@ Cumulonimbus (Cb) Here is the directory contents: + ```shell $ tree . @@ -80,15 +89,17 @@ $ tree ``` Dune stores the files it creates, and a copy of the sources, in a directory named `_build`. You don't need to edit anything there. In a project managed using Git, the `_build` directory should be ignored + ```shell $ echo _build >> .gitignore ``` + You can also configure your editor or IDE to ignore it too. In OCaml, each `.ml` file defines a module. In the `mixtli` project, the file `cloud.ml` defines the `Cloud` module, the file `wmo.ml` defines the `Wmo` module that contains two submodules: `Stratus` and `Cumulus`. Here are the different names: -* `mixtli` is the project's name (it means *cloud* in Nahuatl). +* `mixtli` is the project's name (it means *cloud* in [Nahuatl](https://en.wikipedia.org/wiki/Nahuatl) * `cloud.ml` is the OCaml source file's name, referred as `cloud` in the `dune` file. * `nube` is the executable command's name (it means *cloud* in Spanish). * `Cloud` is the name of the module associated with the file `cloud.ml`. @@ -96,6 +107,7 @@ Here are the different names: * `wmo-clouds` is the name of the package built by this project. The `dune describe` command allows having a look at the project's module structure. Here is its output: + ```lisp ((root /home/cuihtlauac/caml/mixtli-dune) (build_context _build/default) @@ -123,6 +135,7 @@ The `dune describe` command allows having a look at the project's module structu In OCaml, a library is a collection of modules. By default, when Dune builds a library, it wraps the bundled modules into a module. This allows having several modules with the same name, inside different libraries, in the same project. That feature is known as [_namespaces_](https://en.wikipedia.org/wiki/Namespace) for module names. This is similar to what modules do for definitions; they avoid name clashes. Dune creates libraries from directories. Let's look at an example. Here the `lib` directory contains its sources. This is different from the Unix standard, where `lib` stores compiled library binaries. + ```shell $ mkdir lib ``` @@ -138,6 +151,7 @@ The `lib` directory is populated with the following source files: ```ocaml val nimbus : string ``` + **`lib/cumulus.ml`** ```ocaml @@ -155,6 +169,7 @@ let nimbus = "Nimbostratus (Ns)" ``` All the modules found in the `lib` directory are bundled into the `Wmo` module. This module is the same as what we had in the `wmo.ml` file. To avoid redundancy, we delete it: + ```shell $ rm wmo.ml ``` @@ -209,6 +224,7 @@ Using a wrapper file makes several things possible: By default, Dune builds a library from the modules found in the same directory as the `dune` file, but it doesn't look into subdirectories. It is possible to change this behaviour. In this example, we create subdirectories and move files there. + ```shell $ mkdir lib/cumulus lib/stratus $ mv lib/cumulus.ml lib/cumulus/m.ml @@ -243,6 +259,7 @@ The `include_subdirs qualified` stanza works recursively, except on subdirectori It is possible to start an empty Dune project from a single file. Create a fresh directory. + ```shell $ mkdir foo.dir; cd foo.dir ``` @@ -325,6 +342,7 @@ let nimbus = "Nimbostratus (Ns)" ``` In this setup, running `dune utop` allows discovering what's available. + ```ocaml # #show Wmo;; module Wmo : sig module Cumulus = Wmo.Cumulus module Stratus = Wmo.Stratus end @@ -376,6 +394,7 @@ Wrapping can be disabled in Dune's configuration. In that case, the “library” only contains the modules `Cumulus` and `Stratus`, bundled together, side by side. Check the following in `dune utop`, twice. Once with file `lib/wmo.ml` unchanged, and a second time after deleting it. + ```ocaml # #show Cumulus;; module Cumulus : sig val nimbus : string val altus : string end diff --git a/data/tutorials/language/3ds_00_options.md b/data/tutorials/language/3ds_00_options.md index 26e59f78c6..703cef6c4b 100644 --- a/data/tutorials/language/3ds_00_options.md +++ b/data/tutorials/language/3ds_00_options.md @@ -9,6 +9,7 @@ category: "Data Structures" ## Introduction An [option](https://en.wikipedia.org/wiki/Option_type) value wraps another value or contains nothing if there isn't anything to wrap. The predefined type `option` represents such values. + ```ocaml # #show option;; @@ -16,6 +17,7 @@ type 'a option = None | Some of 'a ``` Here are option values: + ```ocaml # Some 42;; - : int option = Some 42 @@ -33,6 +35,7 @@ The option type is useful when the lack of data is better handled as the special ## Exceptions _vs_ Options The function `Sys.getenv : string -> string` from the OCaml standard library queries the value of an environment variable; however, it throws an exception if the variable is not defined. On the other hand, the function `Sys.getenv_opt : string -> string option` does the same, except it returns `None` if the variable is not defined. Here is what may happen if we try to access an undefined environment variable: + ```ocaml # Sys.getenv "UNDEFINED_ENVIRONMENT_VARIABLE";; Exception: Not_found. @@ -50,6 +53,7 @@ Most of the functions in this section, as well as other useful ones, are provide ### Map Over an Option Using pattern matching, it is possible to define functions, allowing to work with option values. Here is `map` of type `('a -> 'b) -> 'a option -> 'b option`. It allows to apply a function to the wrapped value inside an `option`, if present: + ```ocaml let map f = function | None -> None @@ -57,6 +61,7 @@ let map f = function ``` In the standard library, this is `Option.map`. + ```ocaml # Option.map (fun x -> x * x) (Some 3);; - : int option = Some 9 @@ -77,6 +82,7 @@ let join = function ``` In the standard library, this is `Option.join`. + ```ocaml # Option.join (Some (Some 42));; - : int option = Some 42 @@ -91,6 +97,7 @@ In the standard library, this is `Option.join`. ### Access the Content of an Option The function `get` of type `'a option -> 'a` allows access to the value contained inside an `option`. + ```ocaml let get = function | Some v -> v @@ -98,6 +105,7 @@ let get = function ``` Beware, `get o` throws an exception if `o` is `None`. To access the content of an `option` without the risk of raising an exception, the function `value` of type `'a option -> 'a -> 'a` can be used: + ```ocaml let value opt ~default = match opt with | Some v -> v @@ -111,6 +119,7 @@ In the standard library, these functions are `Option.get` and `Option.value`. ### Fold an Option The function `fold` of type `none:'a -> some:('b -> 'a) -> 'b option -> 'a` can be seen as a combination of `map` and `value` + ```ocaml let fold ~none ~some o = o |> Option.map some |> Option.value ~default:none ``` @@ -118,6 +127,7 @@ let fold ~none ~some o = o |> Option.map some |> Option.value ~default:none In the standard library, this function is `Option.fold`. The `Option.fold` function can be used to implement a fall-back logic without writing pattern matching. For instance, here is a function that turns the contents of the `$PATH` environment variable into a list of strings, or the empty list if undefined. This version uses pattern matching: + ```ocaml # let path () = let split_on_colon = String.split_on_char ':' in @@ -129,6 +139,7 @@ val path : unit -> string list = ``` Here is the same function, using `Option.fold`: + ```ocaml # let path () = let split_on_colon = String.split_on_char ':' in @@ -141,6 +152,7 @@ val path : unit -> string list = The `bind` function of type `'a option -> ('a -> 'b option) -> 'b option` works a bit like `map`. But whilst `map` expects a function parameter `f` that returns an unwrapped value of type `b`, `bind` expects an `f` that returns a value already wrapped in an option `'b option`. Here, we display the type of `Option.map`, with parameters flipped and show a possible implementation of `Option.bind`. + ```ocaml # Fun.flip Option.map;; - : 'a option -> ('a -> 'b) -> 'b option = diff --git a/data/tutorials/language/3ds_01_arrays.md b/data/tutorials/language/3ds_01_arrays.md index a831822a5d..7a1cfbb5e6 100644 --- a/data/tutorials/language/3ds_01_arrays.md +++ b/data/tutorials/language/3ds_01_arrays.md @@ -139,6 +139,7 @@ These functions derive a single value from the whole array. For example, they ca To sort an array, we can use the `Array.sort` function. This function takes as arguments: - a comparison function - an array + It sorts the provided array in place and in ascending order, according to the provided comparison function. Sorting performed by `Array.sort` modifies the content of the provided array, which is why it returns `unit`. For example, to sort the array `even_numbers` created above, we can use: ```ocaml diff --git a/data/tutorials/language/3ds_02_maps.md b/data/tutorials/language/3ds_02_maps.md index c18d6c2140..e24bbf2c71 100644 --- a/data/tutorials/language/3ds_02_maps.md +++ b/data/tutorials/language/3ds_02_maps.md @@ -8,18 +8,24 @@ category: "Data Structures" ## Introduction -The [`Map`](/manual/api/Map.html) module lets you create _immutable_ key-value [association -tables](https://en.wikipedia.org/wiki/Associative_array) for your types. Such -maps are never modified, and every operation returns a new map instead. - -**Note**: Maps described in this tutorial should not be confused with map -functions such as `List.map`, `Array.map`, `Option.map`, and others. The maps -described in this tutorial are also called dictionaries or associative tables. - -To use `Map`, we first have to use the [`Map.Make`](/manual/api/Map.Make.html) functor to create our custom -map module. Refer to the [Functors](/docs/functors) for more information on -functors. This functor has a module parameter that defines the keys' type to -be used in the maps, and a function for comparing them. +In the most general sense, the [`Map`](/manual/api/Map.html) module lets you create _immutable_ key-value +[associative array](https://en.wikipedia.org/wiki/Associative_array) for your types. More concretely, +OCaml's `Map` module is implemented using a binary search tree alogorithm to support fast lookups (of O(Log n)). + +**Note**: The concept of a `Map` in this tutorial refers to a data structure that stores a +set of key-value pairs. It is sometimes called a dictionary or an association table. This +is a disinct concept from the maps we've explored in previous lessons, such as `List.map`, +`Array.map`, and `Option.map`, which are functions that operate over data rather than +being data themselves. + +To use `Map`, we first have to use the [`Map.Make`](/manual/api/Map.Make.html) functor to +create our custom map module. Refer to the [Functors](/docs/functors) for more information +on functors. This functor has a module parameter that defines the keys' type to be used in +the maps, and a function for comparing them. + +For an different implementation of an association table in OCaml's Standard Library, see the tutorial +on [Hash Tables](/docs/hash-tables). + ```ocaml # module StringMap = Map.Make(String);; @@ -41,8 +47,10 @@ After naming the newly-created module `StringMap`, OCaml's toplevel displays the module's signature. Since it contains a large number of functions, the output copied here is shortened for brevity `(...)`. -This module doesn't define the values' type. It will be defined when we create -our first map. +When we created the `StringMap` module, we fed the `Map.Make` functor the `String` module to +define the type of the map's keys, which we can observe in the `StringMap`'s signature +(`type key string`). However, we did not yet define the value's type. The value's type will +be defined when we create our first map. ## Creating a Map @@ -50,17 +58,18 @@ The `StringMap` module has an `empty` value that has a type parameter `'a` in its type: `empty : 'a t`. This means that we can use `empty` to create new empty maps where the value is of any type. + +The type of the values can be specified in two ways: +* When you create your new map with an annotation +* By adding an element to the map: + +**Example 1**: By Annotation ```ocaml # let int_map : int StringMap.t = StringMap.empty;; val int_map : int StringMap.t = - -# let float_map : float StringMap.t = StringMap.empty;; -val float_map : float StringMap.t = ``` -The type of the values can be specified in two ways: -* When you create your new map with an annotation -* By adding an element to the map: +**Example 2**: By Adding an Element ```ocaml # let int_map = StringMap.(empty |> add "one" 1);; val int_map : int StringMap.t = @@ -68,7 +77,8 @@ val int_map : int StringMap.t = ## Working With Maps -Throughout the rest of this tutorial, we use the following map: +Throughout the rest of this tutorial, we will use the following map: + ```ocaml # let lucky_numbers = StringMap.of_seq @@ List.to_seq [ ("leostera", 2112); @@ -81,6 +91,7 @@ val lucky_numbers : int StringMap.t = ## Finding Entries in a Map To find entries in a map, use the `find_opt` or `find` functions: + ```ocaml # StringMap.find_opt "leostera" lucky_numbers;; - : int option = Some 2112 @@ -91,7 +102,7 @@ To find entries in a map, use the `find_opt` or `find` functions: When the searched key is present from the map: - `find_opt` returns the associated value, wrapped in an option -- `find` returns the associated +- `find` returns the associated value When the searched key is absent from the map: - `find_opt` returns `None` @@ -99,6 +110,7 @@ When the searched key is absent from the map: We can also use `find_first_opt` and `find_last_opt` if we want to use a predicate function: + ```ocaml # let first_under_10_chars : (string * int) option = StringMap.find_first_opt @@ -116,7 +128,8 @@ not just the value. ## Adding Entries to a Map To add an entry to a map, use the `add` function that takes a key, a value, and -a map. It returns a new map with that key-value pair added: +the map to which it will be added. It returns a new map with that key-value pair added: + ```ocaml # let more_lucky_numbers = lucky_numbers |> StringMap.add "paguzar" 108;; val more_lucky_numbers : int StringMap.t = @@ -136,14 +149,15 @@ Note that the initial map `lucky_numbers` remains unchanged. To remove an entry from a map, use the `remove` function, which takes a key and a map. It returns a new map with that key's entry removed. + ```ocaml -# let less_lucky_numbers = lucky_numbers |> StringMap.remove "divagnz";; -val less_lucky_numbers : int StringMap.t = +# let fewer_lucky_numbers = lucky_numbers |> StringMap.remove "divagnz";; +val fewer_lucky_numbers : int StringMap.t = # StringMap.find_opt "divagnz" lucky_numbers;; - : int option = Some 13 -# StringMap.find_opt "divagnz" less_lucky_numbers;; +# StringMap.find_opt "divagnz" fewer_lucky_numbers;; - : int option = None ``` @@ -174,7 +188,8 @@ You should experiment with different update functions; several behaviors are pos ## Checking if a Key is Contained in a Map -To check if a map contains a key, use the `mem` function: +To check if a key is a member of a map, use the `mem` function: + ```ocaml # StringMap.mem "paguzar" less_lucky_numbers;; - : bool = false @@ -182,9 +197,11 @@ To check if a map contains a key, use the `mem` function: ## Merging Maps -To merge two maps, use the `union` function, which takes two maps, and a -function deciding how to handle entries with identical keys. It returns a new map. -Note that the input maps are not modified. +To merge two maps, use the `union` function. This function takes two maps, a +function deciding how to handle entries with identical keys, and it returns a new map. + +**Note**: As with all the other functions of `Map`, the input maps are not modified. + ```ocaml # StringMap.union;; - : (string -> 'a -> 'a -> 'a option) -> @@ -193,6 +210,7 @@ Note that the input maps are not modified. ``` Here are examples of duplicate key resolution functions: + ```ocaml # let pick_fst key v1 _ = Some v1;; val pick_fst : 'a -> 'b -> 'c -> 'b option = @@ -233,6 +251,7 @@ val drop : 'a -> 'b -> 'c -> 'd option = To filter a map, use the `filter` function. It takes a predicate to filter entries and a map. It returns a new map containing the entries satisfying the predicate. + ```ocaml # let even_numbers = StringMap.filter @@ -244,24 +263,28 @@ val even_numbers : int StringMap.t = ## Map a Map Map modules have a `map` function: + ```ocaml StringMap.map;; - : ('a -> 'b) -> 'a StringMap.t -> 'b StringMap.t = ``` -The `lucky_numbers` map associates string keys with integer values. +The `lucky_numbers` map associates string keys with integer values: + ```ocaml # lucky_numbers;; - : int StringMap.t = ``` Using `StringMap.map`, we create a map associating keys with string values: + ```ocaml # let lucky_strings = StringMap.map string_of_int lucky_numbers;; val lucky_strings : string StringMap.t = ``` The keys are the same in both maps. For each key, a value in `lucky_numbers` is converted into a value in `lucky_strings` using `string_of_int`. + ```ocaml # lucky_numbers |> StringMap.find "leostera" |> string_of_int;; - : string = "2112" @@ -275,17 +298,15 @@ The keys are the same in both maps. For each key, a value in `lucky_numbers` is If you need to create a map with a custom key type, you can call the `Map.Make` functor with a module of your own, provided that it implements two things: -1. A type `t` type with no type parameters +1. A type `t` exposing the type of the map's key 2. A function `compare : t -> t -> int` function that compares `t` values Let's define our custom map below for non-negative numbers. We'll start by defining a module for strings that compares them in case-insensitive way. + ```ocaml -# module Istring : sig - type t - val compare : t -> t -> int - end = struct +# module Istring = struct type t = string let compare a b = String.(compare (lowercase_ascii a) (lowercase_ascii b)) end;; @@ -310,6 +331,13 @@ module IstringMap : val remove : key -> 'a t -> 'a t (* ... *) end + +# let lucky_int_numbers = IstringMap.of_seq @@ List.to_seq [ + ("leostera", 2112); + ("charstring88", 88); + ("divagnz", 13); + ];; +val lucky_int_numbers : int IstringMap.t = ``` ## Conclusion diff --git a/data/tutorials/language/3ds_03_sets.md b/data/tutorials/language/3ds_03_sets.md index 6215aea91d..e407723871 100644 --- a/data/tutorials/language/3ds_03_sets.md +++ b/data/tutorials/language/3ds_03_sets.md @@ -13,6 +13,7 @@ category: "Data Structures" **Disclaimer:** The examples in this tutorial require OCaml 5.1. If you're running a previous version of OCaml , you can either use `elements` instead of `to_list`, which is a new function in OCaml 5.1, or upgrade OCaml by running `opam update`, then `opam upgrade ocaml`. Check your current version with `ocaml --version`. If you need to work with string sets, you must invoke `Set.Make(String)`. That returns a new module. + ```ocaml # module StringSet = Set.Make(String);; module StringSet : @@ -38,6 +39,7 @@ This module also defines two types: ## Creating a Set 1. We can create an empty set using `StringSet.empty`: + ```ocaml # StringSet.empty ;; - : StringSet.t = @@ -51,6 +53,7 @@ For `StringSet.empty`, you can see that the OCaml toplevel displays the placehol (Remember, for OCaml versions before 5.1, it will be `StringeSet.empty |> StringSet.elements;;`) 2. A set with a single element is created using `StringSet.singleton`: + ```ocaml # StringSet.singleton "hello";; - : StringSet.t = @@ -60,6 +63,7 @@ For `StringSet.empty`, you can see that the OCaml toplevel displays the placehol ``` 3. Converting a list into a set using `StringSet.of_list`: + ```ocaml # StringSet.of_list ["hello"; "hi"];; - : StringSet.t = @@ -73,6 +77,7 @@ There's another relevant function `StringSet.of_seq: string Seq.t -> StringSet.t ## Working With Sets Let's look at a few functions for working with sets using these two sets. + ```ocaml # let first_set = ["hello"; "hi"] |> StringSet.of_list;; - : val first_set : StringSet.t = @@ -189,9 +194,11 @@ You can see that this module has the intended behavior: # CISS.singleton "hello" |> CISS.add "HELLO" |> CISS.to_list;; - : string list = ["hello"] ``` + The value `"HELLO"` is not added to the set because it is considered equal to the value `"hello"`, which is already contained in the set. You can use any type for elements, as long as you define a meaningful `compare` operation. + ```ocaml # type color = Red | Green | Blue;; type color = Red | Green | Blue diff --git a/data/tutorials/language/3ds_04_hashtbl.md b/data/tutorials/language/3ds_04_hashtbl.md index c1c4ae05f0..cc3ce4e1c5 100644 --- a/data/tutorials/language/3ds_04_hashtbl.md +++ b/data/tutorials/language/3ds_04_hashtbl.md @@ -15,6 +15,7 @@ create a hash table we could write: # let my_hash = Hashtbl.create 123456;; val my_hash : ('_weak1, '_weak2) Hashtbl.t = ``` + The 123456 is the initial size of the hashtbl. This initial number is just your best guess as to the amount of data that you will be putting into the hash table. The hash table can grow if you under-estimate the diff --git a/data/tutorials/language/3ds_05_seq.md b/data/tutorials/language/3ds_05_seq.md index c5c282de1d..bdcc60d81c 100644 --- a/data/tutorials/language/3ds_05_seq.md +++ b/data/tutorials/language/3ds_05_seq.md @@ -12,7 +12,7 @@ prerequisite_tutorials: ## Introduction Sequences are very much like lists. However, from a pragmatic perspective, one -should imagine they may be infinite. That's the key intuition to understanding +should imagine they can be either finite or infinite. That's the key intuition to understanding and using sequences. To achieve this, sequence elements are computed on demand and not stored in memory. Perhaps more frequently, sequences also allow for reducing memory consumption from linear to constant space @@ -23,20 +23,24 @@ Still in the intro: for people familiar with Python, I believe it would be very One way to look at a value of type `'a Seq.t` is to consider it as a list, but it contains a twist when it's not empty: its tail is frozen. To understand this analogy, -consider how sequences are defined in the standard library: +consider how sequences are defined in the Standard Library: + ```ocaml type 'a node = | Nil | Cons of 'a * 'a t and 'a t = unit -> 'a node ``` + This is the mutually recursive definition of two types: `Seq.node`, which is almost the same as `list`: + ```ocaml type 'a list = | [] | (::) of 'a * 'a list ``` + and `Seq.t`, which is merely a type alias for `unit -> 'a Seq.node`. The whole point of this definition is `Seq.Cons` second component's type, which is a function returning a sequence while its `list` counterpart is a list. Let's @@ -64,29 +68,54 @@ writing `fun _ -> a` or `fun () -> a`. The latter function is called a [_thunk_](https://en.wikipedia.org/wiki/Thunk). Using this terminology, `Seq.t` values are thunks. With the analogy used earlier, `a` is frozen in its thunk. -Here is how to build seemingly infinite sequences of integers: +## Constructing Sequences + +With this understanding, we can manually construct a sequence like so: + +``` ocaml +let my_seq = + fun () -> + Seq.Cons (1, fun () -> Seq.Cons (2, fun () -> Seq.Cons (3, fun () -> Seq.Nil))) +``` + +**Note:** The second component of each `Seq.Con`'s tuple is a function. This has +the effect of providing a means of acquiring a value rather than providing a +value directly. + +We can also construct sequences using functions. Here is how to build an +infinite sequence of integers: + ```ocaml # let rec ints n : int Seq.t = fun () -> Seq.Cons (n, ints (n + 1));; val ints : int -> int Seq.t = ``` + The function `ints n` looks as if building the infinite sequence `(n; n + 1; n + 2; n + 3;...)`. In reality, since machine integers have bounds, the sequence -isn't indefinitely increasing. When reaching `max_int`, it will circle +isn't indefinitely increasing. For technical reasons, when `max_int` is reached, it will circle down to `min_int`. -The OCaml standard library contains a module on sequences called -[`Seq`](/releases/5.0/api/Seq.html). It contains a `Seq.iter` function, which -has the same behaviour as `List.iter`. Writing this: +The OCaml Standard Library contains a module for sequences called +[`Seq`](/releases/api/Seq.html). It contains `Seq.int`, which we implemented above. + +## Iterating Over Sequences + +The OCaml Standard Library also contains a `Seq.iter` function, which has the +same behavior as `List.iter`. Writing this: + ```ocaml # Seq.iter print_int (ints 0);; ``` + in an OCaml toplevel means “print integers forever,” and you have to press `Ctrl-C` to interrupt the execution. The following code is the same infinite loop without any output: + ```ocaml # Seq.iter ignore (ints 0);; ``` -The key point is: it doesn't leak memory. This example is running in constant + +The key point is that it doesn't leak memory. This example runs in constant space. It is effectively nothing more than an infinite loop, which can be confirmed by monitoring the space consumption of the program and by noticing that it spins forever without crashing. Whereas a version of this with a list @@ -94,11 +123,12 @@ that it spins forever without crashing. Whereas a version of this with a list proportional to the running time, and thus would crash by running out of memory pretty quickly. -## Example +## Taking Parts of a Sequence -The `Seq` module of the OCaml standard library contains the definition of the +The `Seq` module of the OCaml Standard Library contains the definition of the function `Seq.take`, which returns a specified number of elements from the beginning of a sequence. Here is a simplified implementation: + ```ocaml let rec take n seq () = if n <= 0 then @@ -108,11 +138,12 @@ let rec take n seq () = | Seq.Cons (x, seq) -> Seq.Cons (x, take (n - 1) seq) | _ -> Seq.Nil ``` + `take n seq` returns, at most, the `n` first elements of the sequence `seq`. If `seq` contains less than `n` elements, an identical sequence is returned. In particular, if `seq` is empty, or `n` is negative, an empty sequence is returned. -Observe the first line of `take`. It is the common pattern for recursive +Observe the first line of our `take` function. It is the common pattern for recursive functions over sequences. The last two parameters are: * a sequence called `seq` * a `unit` value @@ -124,6 +155,7 @@ seq` does not compute anything. It is a partial application and returns a function needing a `unit` to produce a result. This can be used to print integers without looping forever, as shown previously: + ```ocaml # Seq.ints 0 |> Seq.take 43 |> List.of_seq;; - : int list = @@ -132,24 +164,30 @@ This can be used to print integers without looping forever, as shown previously: 41; 42] ``` +## Filtering a Sequence + The `Seq` module also has a function `Seq.filter`: + ```ocaml # Seq.filter;; - : ('a -> bool) -> 'a Seq.t -> 'a Seq.t = ``` + It builds a sequence of elements satisfying a condition. Using `Seq.filter`, taking inspiration from the [trial division](https://en.wikipedia.org/wiki/Trial_division) algorithm, it is possible to define a function which seemingly generates the list of all primes numbers. + ```ocaml let rec trial_div seq () = match seq () with - | Seq.Cons (m, seq) -> Seq.Cons (m, trial_div (Seq.filter (fun n -> n mod m > 0) seq)) - | seq -> seq + | Seq.Cons (m, seq_rest) -> Seq.Cons (m, trial_div (Seq.filter (fun n -> n mod m > 0) seq_rest)) + | Seq.Nil -> Seq.Nil let primes = Seq.ints 2 |> trial_div;; val trial_div : int Seq.t -> int Seq.t = val primes : int Seq.t = ``` -For instance, here is the list of 100 first prime numbers: +For instance, here is a list of 100 first prime numbers: + ```ocaml # primes |> Seq.take 100 |> List.of_seq;; - : int list = @@ -162,11 +200,31 @@ For instance, here is the list of 100 first prime numbers: 509; 521; 523; 541] ``` -The function `trial_div` is recursive in OCaml and common sense. It is defined -using the `rec` keyword and calls itself. However, some call that kind of -function [corecursive](https://en.wikipedia.org/wiki/Corecursion). This word is -used to emphasise that, although it may not terminate, it can indefinitely -produce valid output. +The function `trial_div` is recursive in OCaml and can be understood if we break +it down into its constituent parts. It is defined using the `rec` keyword, allowing the +function to call itself. For each loop in the recursive call, it pattern-matches +on either `Seq.Cons (m, seq)` or the end of the sequence, `Seq.Nil`. + +If it matches on the first branch `Seq.Cons (m, seq)`, we filter the +remaining sequence of all integers that are divisible by `m` before recursively +calling `trial_div` on the filtered sequence. This branch is matched on until we +reach the end of the sequence for every recursive call. + +So far, we recursively traveled down our sequence until we reached the 100th +prime number. Next, we retrace our steps up the recursive trail, wherein we +construct our result by calling `Seq.Cons` on `m` and the previously constructed +filtered sequence beginning with `Seq.Nil`. + +**Side Note**: It may be interesting to learn that `trial_div`, while it can +colloquially be called a recursive, is an example of a kind of recursion called +[corecursion](https://en.wikipedia.org/wiki/Corecursion). Corecursion differs +from recursion in that it constructs results incrementally rather than consuming +it's input incrementally. Unlike traditional recursion, which works towards a +base case, corecursive functions must indefinitely produce values as a stream. The `trial_div` function is corecursive +because it does not immediately compute the complete sequence of primes. Instead, it +produces prime numbers on-demand, filtering and deferring further computation until +more elements are requested. This allows the sequence to be processed +incrementally rather than requiring a complete traversal upfront. ## Unfolding Sequences @@ -176,60 +234,95 @@ instance: * `Seq.map` * `Seq.fold_left` -All those are also available for [`Array`](/manual/api/Array.html), `List`, and `Set` and behave -essentially the same. Observe that there is no `fold_right` function. Since -OCaml 4.11, there is something which isn't (yet) available on other types: -`unfold`. Here is how it is implemented: +All of these kinds of higher-order functions are also available for +[`Array`](/manual/api/Array.html), `List`, and `Set` and behave essentially the +same. Observe that there is no `fold_right` function. Since OCaml 4.11, there is +something which isn't (yet) available on other types: `unfold`. Here is how it +is implemented: + ```ocaml let rec unfold f x () = match f x with | None -> Seq.Nil | Some (x, seq) -> Seq.Cons (x, unfold f seq) ``` + And here is its type: + ```ocaml val unfold : ('a -> ('b * 'a) option) -> 'a -> 'b Seq.t = ``` + Unlike previously mentioned iterators, `Seq.unfold` does not have a sequence parameter, but a sequence result. `unfold` provides a general means to build -sequences. The result returned by `Seq.unfold f x` is the sequence built by accumulating the results of successive calls to `f` until it returns `None`. This is: +sequences. The result returned by `Seq.unfold f x` is the sequence built by +accumulating the results of successive calls to `f` until it returns `None`. +This is: + ``` (fst p₀, fst p₁, fst p₂, fst p₃, fst p₄, ...) ``` + where `Some p₀ = f x` and `Some pₙ₊₁ = f (snd pₙ)`. For instance, `Seq.ints` can be implemented using `Seq.unfold` in a fairly compact way: + ```ocaml # let ints = Seq.unfold (fun n -> Some (n, n + 1));; val ints : int -> int Seq.t = ``` - -As a fun fact, one should observe `map` over sequences can be implemented using +As a fun fact, we can observe that a `map` over sequences can be implemented using `Seq.unfold`. Here is how to write it: + ```ocaml # let map f = Seq.unfold (fun seq -> seq |> Seq.uncons |> Option.map (fun (x, seq) -> (f x, seq)));; val map : ('a -> 'b) -> 'a Seq.t -> 'b Seq.t = ``` -Here is a quick check: + +We can check our `map` function by applying a square root function to a sequence: + ```ocaml # Seq.ints 0 |> map (fun x -> x * x) |> Seq.take 10 |> List.of_seq;; - : int list = [0; 1; 4; 9; 16; 25; 36; 49; 64; 81] ``` + The function `Seq.uncons` returns the head and tail of a sequence if it is not empty. Otherwise, it returns `None`. -Using this function: +### Reading a File with `Seq.Unfold` + +For the next example, we will demonstrate the versatility of `Seq.unfold` by +using it to read a file. + +Before doing so, let's define a function that reads a file's line from a +provided channel, with the type signature needed by `Seq.unfold`. + ```ocaml -let input_line_opt chan = - try Some (input_line chan, chan) - with End_of_file -> None +# let input_line_opt chan = + try Some (In_Channel.input_line chan, chan) + with End_of_file -> None;; +val input_line_opt : in_channel -> (string * in_channel) option = +``` + +**Note**: To make the code in the next section work, create a file named "README.md" and add dummy content. We use a file generated by the following command: + +``` shell +cat > README.md < Seq.unfold input_line_opt |> Seq.iter print_endline; -close_in cin +# let cin = open_in "README.md" in + cin |> Seq.unfold In_channel.input_line_opt |> Seq.iter print_endline; + close_in cin;; +This is the first line. +This is the second line. +- : unit = () ``` + Although this looks like a possible way to define the [Fibonacci sequence](https://en.wikipedia.org/wiki/Fibonacci_number): + ```ocaml # let rec fibs m n = Seq.cons m (fibs n (n + m));; val fibs : int -> int -> int Seq.t = ``` + It actually isn't. It's an unending recursion which blows away the stack. + ``` # fibs 0 1;; Stack overflow during evaluation (looping recursion?). ``` -This definition is behaving as expected (spot the differences, there are four): + +This definition is behaving as expected (spot the differences, there are four): + ```ocaml # let rec fibs m n () = Seq.Cons (m, fibs n (n + m));; val fibs : int -> int -> int Seq.t = ``` + It can be used to produce some Fibonacci numbers: + ```ocaml # fibs 0 1 |> Seq.take 10 |> List.of_seq;; - : int list = [0; 1; 1; 2; 3; 5; 8; 13; 21; 34] ``` + Why is it so? The key difference lies in the recursive call `fibs n (n + m)`. In the former definition, the application is complete because `fibs` is provided with all the arguments it expects. In the latter definition, the application is partial because the `()` argument is missing. Since evaluation is [eager](https://en.wikipedia.org/wiki/Evaluation_strategy#Eager_evaluation) in -OCaml, in the former case, evaluation of the recursive call is triggered and a -non-terminating looping occurs. In contrast, in the latter case, the partially +OCaml, in the former case evaluation of the recursive call is triggered again and again, without ever terminating (this is what "looping recursion" in the error message refers to). In the latter case, the partially applied function is immediately returned as a [closure](https://en.wikipedia.org/wiki/Closure_(computer_programming)). Sequences are functions, as stated by their type: + ```ocaml # #show Seq.t;; type 'a t = unit -> 'a Seq.node ``` + Functions working with sequences must be written accordingly. * Sequence consumer: partially applied function parameter * Sequence producer: partially applied function result @@ -333,20 +444,26 @@ Throughout the standard library, sequences are used as a bridge to perform conversions between many datatypes. For instance, here are the signatures of some of those functions: * Lists + ```ocaml val List.to_seq : 'a list -> 'a Seq.t val List.of_seq : 'a Seq.t -> 'a list ``` + * Arrays + ```ocaml val Array.to_seq : 'a array -> 'a Seq.t val Array.of_seq : 'a Seq.t -> 'a array ``` + * Strings + ```ocaml val String.to_seq : string -> char Seq.t val String.of_seq : char Seq.t -> string ``` + Similar functions are also provided for sets, maps, hash tables (`Hashtbl`), and others. When implementing a datatype module, it is advised to expose `to_seq` and `of_seq` functions. @@ -365,7 +482,7 @@ There used to be a module called [`Stream`](/releases/4.13/api/Stream.html) in the OCaml standard library. It was [removed](https://github.com/ocaml/ocaml/pull/10482) in 2021 with the release of OCaml 4.14. Beware books and documentation written before may still mention it. - ```ocaml Printf.printf "This program has been compiled by user: %s" [%get_env "USER"] - ``` When you compile the code with the preprocessor, it will replace [%get_env "USER"] with the content of the USER environment variable. If the USER environment variable is set to "JohnDoe" for example, the line would become: @@ -27,7 +26,6 @@ When you compile the code with the preprocessor, it will replace [%get_env "USER ```ocaml Printf.printf "This program has been compiled by user: %s" "JohnDoe" - ``` @@ -141,7 +139,7 @@ module files using our previously written `preprocessor.sh`: The complexities of a programming language syntax makes it very hard to manipulate text in a way that is tied to the syntax. Suppose for instance that, -similarly to the previous example, you want to rewrite all occurences of "World" +similarly to the previous example, you want to rewrite all occurrences of "World" by "Universe," but _inside the OCaml strings of the program_ only. It is quite involved and requires a good knowledge of the OCaml syntax to do so, as there are several delimiters for strings (such as `{| ...|}`) and line breaks, or @@ -200,7 +198,6 @@ or even directly with the OCaml toplevel using the option `-dparsetree` (also available in UTop). ```shell - $ ocaml -dparsetree [Omitted output] # let x = 1 + 2 ;; @@ -434,6 +431,7 @@ type t = int [@@deriving_inline yojson] ``` Now, we run the PPX and promote the generated code in the original file: + ```shell $ opam exec -- dune build @lint File "lib/lib.ml", line 1, characters 0-0: @@ -452,8 +450,10 @@ index 4999e06..5516d41 100644 [@@@deriving.end] Promoting _build/default/lib/lib.ml.lint-corrected to lib/lib.ml. ``` + The file now contains the generated value. While it is still a development dependency, the PPX dependency can be dropped for compiling the project: + ```shell $ cat lib.ml type t = int [@@deriving_inline yojson] diff --git a/data/tutorials/language/4ad_01_operators.md b/data/tutorials/language/4ad_01_operators.md index 9ead141fce..d06d428613 100644 --- a/data/tutorials/language/4ad_01_operators.md +++ b/data/tutorials/language/4ad_01_operators.md @@ -16,6 +16,7 @@ The learning goals of this tutorial are: ## Using Binary Operators In OCaml, almost all binary operators are regular functions. The function underlying an operator is referred by surrounding the operator symbol with parentheses. Here are the addition, string concatenation, and equality functions: + ```ocaml # (+);; - : int -> int -> int = @@ -26,12 +27,14 @@ In OCaml, almost all binary operators are regular functions. The function underl ``` **Note**: the operator symbol for multiplication is ` * `, but can't be referred as `(*)`. This is because comments in OCaml are delimited by `(*` and `*)`. To resolve the parsing ambiguity, space characters must be inserted to get the multiplication function. + ```ocaml # ( * );; - : int -> int -> int = ``` Using operators as functions is convenient when combined with partial application. For instance, here is how to get the values that are greater than or equal to 10 in a list of integers, using the function `List.filter` and an operator. + ```ocaml # List.filter;; - : ('a -> bool) -> 'a list -> 'a list = @@ -56,6 +59,7 @@ Finally, in the third line, all the arguments expected by `List.filter` are prov ## Defining Binary Operators It is also possible to define binary operators. Here is an example: + ```ocaml # let cat s1 s2 = s1 ^ " " ^ s2;; val cat : string -> string -> string = @@ -71,6 +75,7 @@ It is a recommended practice to define operators in two steps, like shown in the ## Unary Operators Unary operators are also called prefix operators. In some contexts, it can make sense to shorten a function's name into a symbol. This is often used as a way to shorten the name of a function that performs some sort of conversion over its argument. + ```ocaml # let ( !! ) = Lazy.force;; val ( !! ) : 'a lazy_t -> 'a = @@ -123,6 +128,7 @@ Tips: ## Operator Associativity and Precedence Let's illustrate operator associativity with an example. The following function concatenates its string arguments, surrounded by `|` characters and separated by a `_` character. + ```ocaml # let par s1 s2 = "|" ^ s1 ^ "_" ^ s2 ^ "|";; val par : string -> string -> string = @@ -132,6 +138,7 @@ val par : string -> string -> string = ``` Let's turn `par` into two different operators: + ```ocaml # let ( @^ ) = par;; val ( @^ ) : string -> string -> string = @@ -141,6 +148,7 @@ val ( &^ ) : string -> string -> string = ``` At first sight, operators `@^` and `&^` are the same. However, the OCaml parser allows forming expressions using several operators without parentheses. + ```ocaml # "foo" @^ "bar" @^ "bus";; - : string = "|foo_|bar_bus||" @@ -154,6 +162,7 @@ Although both expressions are calling the same function (`par`), they are evalua 1. Expression `"foo" &^ "bar" &^ "bus"` is evaluated as if it was `"(foo" &^ "bar") &^ "bus"`. Parentheses are added at the left, therefore `&^` _associates to the left_ Operator _precedence_ rules how expressions combining different operators without parentheses are interpreted. For instance, using the same operators, here is how expressions using both are evaluated: + ```ocaml # "foo" &^ "bar" @^ "bus";; - : string = "|foo_|bar_bus||" @@ -176,6 +185,7 @@ The complete list of precedence is longer because it includes the predefined ope OCaml allows the creation of custom `let` operators. This is often used on monad-related functions such as `Option.bind` or `List.concat_map`. See [Monads](/docs/monads) for more on this topic. The `doi_parts` function attempts to extract the registrant and identifier parts from string expected to contain a [Digital Object Identifier (DOI)](https://en.wikipedia.org/wiki/Digital_object_identifier). + ```ocaml # let ( let* ) = Option.bind;; val ( let* ) : 'a option -> ('a -> 'b option) -> 'b option = @@ -198,7 +208,6 @@ val ( let* ) : 'a option -> ('a -> 'b option) -> 'b option = # doi_parts "https://doi.org/10.1000/182";; - : (string * string) option = Some ("1000", "182") - ``` This function is using `Option.bind` as a custom binder over the calls to `rindex_opt` and `rindex_from_opt`. This allows to only consider the case where both searches are successful and return the positions of the found characters. If any of them fails, `doi_parts` implicitly returns `None`. diff --git a/data/tutorials/language/4ad_02_objects.md b/data/tutorials/language/4ad_02_objects.md index e2ef19578d..d304c46d4c 100644 --- a/data/tutorials/language/4ad_02_objects.md +++ b/data/tutorials/language/4ad_02_objects.md @@ -93,6 +93,7 @@ object. We use the familiar `new` operator: # let s = new stack_of_ints;; val s : stack_of_ints = ``` + Now we'll push and pop some elements off the stack: ```ocaml @@ -115,6 +116,7 @@ Popped 2 off the stack. Popped 1 off the stack. - : unit = () ``` + Notice the syntax. `object#method` means call `method` on `object`. This is the same as `object.method` or `object->method` that you will be familiar with in imperative languages. @@ -245,6 +247,7 @@ widget (superclass for all widgets) | +-------------> label ``` + (Notice that a `button` is a `container` because it can contain either a label or an image, depending on what is displayed on the button). @@ -265,6 +268,7 @@ Error: Some type variables are unbound in this type: object method get_name : 'a method virtual repaint : unit end The method get_name has type 'a where 'a is unbound ``` + Oops! I forgot that OCaml cannot infer the type of `name` so will assume that it is `'a`. But that defines a polymorphic class, and I didn't declare the class as polymorphic (`class ['a] widget`). I need to narrow @@ -280,6 +284,7 @@ the type of `name` like this: class virtual widget : string -> object method get_name : string method virtual repaint : unit end ``` + Now there are several new things going on in this code. Firstly, the class contains an **initialiser**. This is an argument to the class (`name`) which you can think of as exactly the equivalent of an argument @@ -294,6 +299,7 @@ public class Widget } } ``` + In OCaml, a constructor constructs the whole class; it's not just a specially named function, so we write the arguments as if they are arguments to the class: @@ -366,10 +372,10 @@ Notes: basically comes down to the fact that OCaml's linked lists are immutable. Let's imagine that someone wrote this code: - ```ocaml - # let list = container#get_widgets in - x :: list;; - ``` +```ocaml +# let list = container#get_widgets in + x :: list;; +``` Would this modify the private internal representation of my `container` class, by prepending `x` to the list of widgets? No it wouldn't. If you run @@ -393,6 +399,7 @@ and I also use an anonymous function expression that might be unfamiliar: # (fun w -> w#repaint);; - : < repaint : 'a; .. > -> 'a = ``` + This defines an anonymous function with one argument `w` that just calls `w#repaint` (the `repaint` method on widget `w`). @@ -490,6 +497,7 @@ class label : string -> string -> object method get_name : string method repaint : unit end ``` + Let's create a label which says "Press me!" and add it to the button: ```ocaml @@ -513,6 +521,7 @@ class name = (* ... *) end ``` + The reference to `self` names the object, allowing you to call methods in the same class or pass the object to functions outside the class. In other words, it's exactly the same as @@ -535,6 +544,7 @@ Error: This expression has type label but an expression was expected of type button The first object type has no method add ``` + We created a button `b` and a label `l` and then tried to create a list containing both, but we got an error. Yet `b` and `l` are both `widget`s, so maybe we can't put them into the same list because OCaml can't guess @@ -629,6 +639,7 @@ but doing so can make things clearer. We can do it like this: # type counter = ;; type counter = < get : int; incr : unit > ``` + Compare with an equivalent record type definition: ```ocaml @@ -637,6 +648,7 @@ Compare with an equivalent record type definition: incr : unit -> unit};; type counter_r = { get : unit -> int; incr : unit -> unit; } ``` + The implementation of a record working like our object would be: ```ocaml @@ -646,6 +658,7 @@ The implementation of a record working like our object would be: incr = (fun () -> incr n)};; val r : counter_r = {get = ; incr = } ``` + In terms of functionality, both the object and the record are similar, but each solution has its own advantages: diff --git a/data/tutorials/language/5rt_01_garbage-collector.md b/data/tutorials/language/5rt_01_garbage-collector.md index 8fe9ae94de..5cb0ab3626 100644 --- a/data/tutorials/language/5rt_01_garbage-collector.md +++ b/data/tutorials/language/5rt_01_garbage-collector.md @@ -167,7 +167,6 @@ profile). This setting can be overridden via the `s=` argument to `OCAMLRUNPARAM`. You can change it after the program has started by calling the `Gc.set` function: - ```ocaml env=tune # open Core;; # let c = Gc.get ();; diff --git a/data/tutorials/language/5rt_02_compiler_frontend.md b/data/tutorials/language/5rt_02_compiler_frontend.md index 9d1c89d2bb..a5ad1355d7 100644 --- a/data/tutorials/language/5rt_02_compiler_frontend.md +++ b/data/tutorials/language/5rt_02_compiler_frontend.md @@ -288,7 +288,6 @@ illustrate their use without requiring any external tools. Let's first look at the use of the standalone attribute `@@@warning` to toggle an OCaml compiler warning. - ```ocaml env=main # module Abc = struct @@ -1195,7 +1194,6 @@ $ ocamlc -dparsetree typedef.ml 2>&1 None ] ] - ``` This is rather a lot of output for a simple two-line program, but it shows @@ -1247,7 +1245,6 @@ $ ocamlc -dtypedtree typedef.ml 2>&1 [] ] ] - ``` The typed AST is more explicit than the untyped syntax tree. For instance, diff --git a/data/tutorials/language/5rt_03_compiler_backend.md b/data/tutorials/language/5rt_03_compiler_backend.md index 6dbbb93c27..214564f2e6 100644 --- a/data/tutorials/language/5rt_03_compiler_backend.md +++ b/data/tutorials/language/5rt_03_compiler_backend.md @@ -275,7 +275,6 @@ Estimated testing time 750ms (3 benchmarks x 250ms). Change using '-quota'. Monomorphic large pattern 6.54ns 67.89% Monomorphic small pattern 9.63ns 100.00% Polymorphic large pattern 9.63ns 99.97% - ``` These results confirm the performance hypothesis that we obtained earlier by @@ -346,7 +345,6 @@ L2: closure L1, 0 makeblock 1, 0 pop 1 setglobal Pattern_monomorphic_small! - ``` The preceding bytecode has been simplified from the lambda form into a set of @@ -420,7 +418,6 @@ bytecode archive: ``` $ ocamlc -a -o mylib.cma a.cmo b.cmo -dllib -lmylib - ``` The `dllib` flag embeds the arguments in the archive file. Any subsequent @@ -434,7 +431,6 @@ a *custom runtime* mode and is built as follows: ``` $ ocamlc -a -o mylib.cma -custom a.cmo b.cmo -cclib -lmylib - ``` The custom mode is the most similar mode to native code compilation, as both @@ -847,8 +843,6 @@ output: (libraries core)) ``` - - ```sh dir=examples/back-end/alternate_list $ opam exec -- dune build alternate_list.exe $ ./_build/default/alternate_list.exe -ascii -quota 1 diff --git a/data/tutorials/platform/1_06_configuring_your_editor.md b/data/tutorials/platform/1_06_configuring_your_editor.md deleted file mode 100644 index 8cfbf1b13f..0000000000 --- a/data/tutorials/platform/1_06_configuring_your_editor.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -id: "configuring-your-editor" -title: "Configuring Your Editor" -description: | - How to set up Editor support for OCaml on VSCode, Vim and Emacs -category: "Editor Support" ---- - -OCaml has plugins for many editors, but the most actively maintained are for Visual Studio Code, Emacs, and Vim. - -## Visual Studio Code - -> **TL;DR** -> -> Install the VSCode extension `ocamllabs.ocaml-platform` and the packages `ocaml-lsp-server` and `ocamlformat` in your [opam switch](/docs/opam-switch-introduction). - -Install the [OCaml Platform Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=ocamllabs.ocaml-platform) from the Visual Studio Marketplace. - -The extension depends on OCaml LSP and ocamlformat. To install them in your switch, you can run: - -```shell -$ opam install ocaml-lsp-server ocamlformat -``` - -Upon first loading an OCaml source file, you may be prompted to select the toolchain in use. Pick the version of OCaml you are using, e.g., 4.14.0, from the list. - -### Editor Features at Your Disposal -If your editor is setup correctly, here are some important features you can begin using to your advantage: -#### 1) Hovering for Type Information: - -![VSCode Hovering](/media/tutorials/vscode-hover.gif) - -This is a great feature that let's you see type information of any OCaml variable or function. All you have to do is place your cursor over the code and it will be displayed in the tooltip. - -#### 2) Jump to Definitions With `Ctrl + Click`: - -![VSCode Ctrl click](/media/tutorials/vscode-ctrl-click.gif) - -If you hold down the Ctrl key while hovering, the code appears as a clickable link which if clicked takes you to the file where the implementation is. This can be great if you want to understand how a piece of code works under the hood. In this example, hovering and `Ctrl + Clicking` over the `peek` method of the `Queue` module will take you to the definiton of the `peek` method itself and how it is implemented. - -#### 3) OCaml Commands With `Ctrl + Shift + P`: - -![VSCode OCaml Commands](/media/tutorials/vscode-ocaml-commands.gif) - -Pressing the key combination Ctrl + Shift + P opens a modal dialog at the top. If you type the word `ocaml`, you will be presented with a list of various OCaml commands at your disposal which can be used for different purposes. - -### Windows Users - -If you used the DkML distribution, you will need to: - 1. Go to `File` > `Preferences` > `Settings` view (or press `Ctrl ,`) - 2. Select `User` > `Extensions` > `OCaml Platform` - 3. Uncheck `OCaml: Use OCaml Env`. That's it! - -## Vim and Emacs - -**For Vim and Emacs**, we won't use the LSP server but rather directly talk to Merlin. - -```shell -$ opam install merlin -``` - -After installing Merlin above, instructions will be printed on how to link Merlin with your editor. If you do not have them visible, just run this command: - -```shell -$ opam user-setup install -``` - -### Talking to Merlin - -#### Getting Type Information - -**Vim** - -![Vim Type information](/media/tutorials/vim-type-info.gif) - -- In the Vim editor, press the Esc to enter command mode. -- Place the cursor over the variable. -- Type `:MerlinTypeOf` and press Enter. -- The type information will be displayed in the command bar. -Other Merlin commands for Vim are available and you can checkout their usage on the [Merlin official documentation for Vim](https://ocaml.github.io/merlin/editor/vim/). - -**Emacs** - -![Emacs Type information](/media/tutorials/emacs-type-info.gif) - -- In the Emacs editor, place you cursor over the variable. -- Use the keyboard shortcut Alt + x followed by `merlin-type-enclosing` -- The type information will be displayed in the mini-buffer. -Other Merlin commands for Emacs are available and you can checkout their usage on the [Merlin Official documentation for Emacs](https://ocaml.github.io/merlin/editor/emacs/). diff --git a/data/tutorials/platform/2_08_odoc.md b/data/tutorials/platform/2_08_odoc.md index 5b6689a679..e343527715 100644 --- a/data/tutorials/platform/2_08_odoc.md +++ b/data/tutorials/platform/2_08_odoc.md @@ -43,4 +43,4 @@ include this stanza: A common place to put `.mld` files is a directory named `doc` or `docs`. For more information on how to write documentation pages for `odoc`, -see the [`odoc` for authors documentation](https://ocaml.github.io/odoc/odoc_for_authors.html#doc-pages). +see the [`odoc` for authors documentation](https://ocaml.github.io/odoc/odoc/odoc_for_authors.html). diff --git a/data/v2/conferences/ocaml/2013/call.md b/data/v2/conferences/ocaml/2013/call.md new file mode 100644 index 0000000000..4668644b77 --- /dev/null +++ b/data/v2/conferences/ocaml/2013/call.md @@ -0,0 +1,81 @@ + + +``` +============================================================================== + + OCAML 2013 + The OCaml Users and Developers Workshop + http://ocaml.org/meetings/ocaml/2013/ + Boston, Massachusetts, USA + September 24, 2013 + + CALL FOR PRESENTATIONS + + Co-located with ICFP 2013 + Sponsored by SIGPLAN + + Talk Proposal Submission Extended Deadline: + June 18, 2013 (anywhere on earth) + +============================================================================== + +The first occurrence of the OCaml Users and Developers Workshop was +colocated with ICFP 2012, in Copenhagen, following the OCaml Meetings +in Paris in 2010 and 2011. OCaml 2013 will be held on September 24, +2013, in Boston, colocated with ICFP 2013. + +The OCaml Users and Developers Workshop brings together industrial +users of OCaml with academics and hackers who are working on extending +the language, type system and tools. Discussions will focus on the +practical aspects of OCaml programming and the nitty gritty of the +tool-chain and upcoming improvements and changes. Thus, we aim to +solicit talks on all aspects related to improving the use or +development of the language and of its programming environment, +including, for example: + +- compiler developments, new backends, runtime and architectures + +- practical type system improvements, such as (but not exhaustively) + GADTs, first-class modules, generic programming, or dependent types + +- new library or application releases, and their design rationales + +- tool enhancements by commercial consultants + +- prominent industrial uses of OCaml, or deployments in unusual + situations. + +It will be an informal meeting, with an online scribe report of the +meeting, but no formal proceedings. Slides of presentations will be +available online from the workshop homepage. + +To submit a talk, please register a description of the talk (about 2 +pages long) at http://ocaml.org/meetings/ocaml/2013/talks/ providing a +clear statement of what will be brought by the talk: the problems that +are addressed, the technical solutions or methods that are +proposed. If you wish to perform a demo or require any special setup, +we will do our best to accommodate you. + +Schedule +======== + +Abstract Submission (extended) Deadline: June 18, 2013 (anywhere on earth) +Notification to Speakers: Friday, July 7, 2013 +Workshop: Tuesday, September 24, 2013 + +Program Committee +================= + +* Damien Doligez, INRIA Paris-Rocquencourt, France +* Jun Furuse, Standard Chartered Bank, Singapore +* Jacques Le Normand, Google, USA +* Michel Mauny, ENSTA-ParisTech, France (chair) +* Mark Shinwell, Jane Street Europe, UK +* David Walker, Princeton University, USA +* Jeremy Yallop, University of Cambridge, UK +* Sarah Zennou, EADS IW, France + +If you have any questions, please e-mail: +Michel Mauny + +``` diff --git a/data/v2/conferences/ocaml/2013/index.md b/data/v2/conferences/ocaml/2013/index.md new file mode 100644 index 0000000000..49c6cefa61 --- /dev/null +++ b/data/v2/conferences/ocaml/2013/index.md @@ -0,0 +1,67 @@ + + +*Table of contents* + +OCaml 2013 +========== + +**The OCaml Users and Developers Workshop** +Boston (MA, USA), September 24, 2013 +Colocated with [ICFP 2013](http://icfpconference.org/icfp2013/) + +The meeting is an informal community gathering of users of the language, +library authors, and developers, using and extending OCaml in new ways. + +News +---- + +- October 7, 2013: The [final program, with links to papers and + slides](program.html) is available. +- July 11, 2013: The [preliminary program](program.html) is available. +- June 7, 2013: The submission deadline has been extended to June 18, + anywhere on earth. +- May 7, 2013: The [submission + site](https://www.easychair.org/conferences/?conf=ocaml2013) is now + open! Please submit a presentation before June 7. +- May 7, 2013: The [submission + site](https://www.easychair.org/conferences/?conf=ocaml2013) is now + open! Please submit a presentation before June 7 June 18 + (anywhere on earth). +- April 16, 2013: [workshop announcement](call.html). The [submission + site](talks/) should open in the next days. + +Important dates +--------------- + +- June 18, 2013 (anywhere on earth): Extended deadline for submissions +- July 7, 2013: Notification to speakers +- September 24, 2013: Workshop + +Call for presentations +---------------------- + +Please consider submitting a presentation, and/or join us in Boston! See +[here the call for presentations](call.html). + +Program Committee +----------------- + +- Damien Doligez, INRIA Paris-Rocquencourt, France +- Jun Furuse, Standard Chartered Bank, Singapore +- Jacques Le Normand, Google, USA +- Michel Mauny, ENSTA-ParisTech, France (chair) +- Mark Shinwell, Jane Street Europe, UK +- David Walker, Princeton University, USA +- Jeremy Yallop, University of Cambridge, UK +- Sarah Zennou, EADS IW, France + +History +------- + +The [first occurrence of the OCaml Users and Developers +Workshop](http://oud.ocaml.org/2012/) was colocated with [ICFP +2012](http://icfpconference.org/icfp2012/), in Copenhagen, following the +*OCaml User Meetings* in Paris in [2008](../2008/), 2010 and [2011](../2011/) +and in Grenoble in [2009](../2009/). Building on the success of +past events, OCaml 2013 will be held on September 24, 2013, in Boston, +colocated with [ICFP 2013](http://icfpconference.org/icfp2013/). diff --git a/data/v2/conferences/ocaml/2013/program.md b/data/v2/conferences/ocaml/2013/program.md new file mode 100644 index 0000000000..8404a40dc8 --- /dev/null +++ b/data/v2/conferences/ocaml/2013/program.md @@ -0,0 +1,123 @@ + + +OCaml 2013 - Program +-------------------- + +### The OCaml Users and Developers Workshop + +#### Boston (MA, USA), September 24, 2013 + +#### Colocated with ICFP 2013 + +#### 09:00-09:10 - Welcome + +#### 09:10-10:10 - Applications + +Accessing and using weather-related data in OCaml +([paper](proposals/weather-related-data.pdf), +[slides](slides/carty.pdf)), by Hezekiah Carty (MDA Information Systems +LLC, USA) + +The Frenetic Network Controller ([paper](proposals/frenetic.pdf), +[slides](slides/guha.pdf)), by Nate Foster (Cornell University, USA), +Arjun Guha (UMass Amherst, USA) and Frenetic Contributors (The Frenetic +Project, USA) + +Pfff: PHP Program analysis at Facebook +([paper](https://github.com/facebook/pfff/wiki/Main), +[slides](slides/padioleau.pdf)), by Yoann Padioleau (Facebook, USA) + +#### 10:10-10:30 - Break + +#### 10:30-11:30 - Bindings + +The design of the wxOCaml library ([paper](proposals/wxocaml.pdf), +[slides](slides/lefessant.pdf)), by Fabrice Le Fessant (INRIA +Paris-Rocquencourt and OCamlPro SAS, France) + +Goji: an Automated Tool for Building High Level OCaml-JavaScript +Interfaces ([paper](proposals/goji.pdf), [slides](slides/canou.pdf)), by +Benjamin Canou (Université Pierre et Marie Curie, LIP6 UMR 7606, France) + +ctypes: foreign calls in your native language +([paper](proposals/ctypes.pdf)), by Jeremy Yallop (University of +Cambridge, UK) + +#### 11:30-11:50 - Break + +#### 11:50-12:30 - OCaml News + +The State of OCaml (invited, [slides](slides/leroy.pdf)), Xavier Leroy +(INRIA Paris-Rocquencourt, France + +The OCaml Platform v0.1 ([paper](proposals/platform.pdf), +[slides](slides/madhavapeddy.pdf)), by Anil Madhavapeddy (University of +Cambridge, UK), Amir Chaudhry (University of Cambridge, UK), Thomas +Gazagnaire (OCamlPro SAS, France), David Sheets (University of +Cambridge, UK), Philippe Wang (University of Cambridge, UK), Leo White +(University of Cambridge, UK) and Jeremy Yallop (University of +Cambridge, UK) + +#### 12:30-14:00 - Lunch + +#### 14:00-15:00 - Compilation + +Extensions points for OCaml (invited, [slides](slides/white.pdf)), by +Leo White (University of Cambridge, UK) + +High-Performance GPGPU Programming with OCaml +([paper](proposals/gpgpu.pdf), [slides](slides/bourgoin.pdf)), by +Mathias Bourgoin (Université Pierre et Marie Curie, LIP6 UMR 7606, +France), Emmmanuel Chailloux (Université Pierre et Marie Curie, LIP6 UMR +7606, France) and Jean-Luc Lamotte (Université Pierre et Marie Curie, +LIP6 UMR 7606, France) + +Improving OCaml high level optimisations +([paper](proposals/optimizations.pdf), [slides](slides/chambart.pdf)), +by Pierre Chambart (OCamlPro SAS, France) + +#### 15:00-15:20 - Break + +#### 15:20-16:20 - Types + +A new implementation of OCaml formats based on GADTs +([paper](proposals/formats-as-gadts.pdf), [slides](slides/vaugon.pdf)), +by Benoît Vaugon (ENSTA-ParisTech, France) + +Runtime types in OCaml ([paper](proposals/runtime-types.pdf), +[slides](slides/henry.pdf)), by Grégoire Henry (INRIA +Paris-Rocquencourt, France) and Jacques Garrigue (Nagoya University, +Japan) + +On variance, injectivity, and abstraction +([paper](proposals/injectivity.pdf), [slides](slides/garrigue.pdf)), by +Jacques Garrigue (Nagoya University, Japan) + +#### 16:20-16:40 - Break + +#### 16:40-17:40 - Tools + +Ocamlot: OCaml Online Testing ([paper](proposals/ocamlot.pdf), +[slides](slides/sheets.pdf)), by David Sheets (University of Cambridge, +UK), Anil Madhavapeddy (University of Cambridge, UK), Amir Chaudhry +(University of Cambridge, UK) and Thomas Gazagnaire (OCamlPro SAS, +France) + +Merlin, an assistant for editing OCaml code +([paper](proposals/merlin.pdf)), by Frédéric Bour (Université +Paris-Diderot, France), Thomas Refis (Université Paris-Diderot, France) +and Simon Castellan (Université Paris-Diderot, France) + +Profiling the Memory Usage of OCaml Applications without Changing their +Behavior ([paper](proposals/profiling-memory.pdf), +[slides](slides/bozman.pdf)), by Çagdas Bozman (OCamlPro SAS, INRIA +Paris-Rocquencourt and ENSTA-Paristech, France), Michel Mauny +(ENSTA-ParisTech, France), Fabrice Le Fessant (INRIA Paris-Rocquencourt +and OCamlPro SAS, France) and Thomas Gazagnaire (OCamlPro SAS, France) + +Core bench: micro-benchmarking for OCaml +([paper](proposals/core-bench.pdf), [slides](slides/james.pdf)), by +Christopher Hardin (Jane Street Capital, USA) and James Roshan (Jane +Street Capital, USA) + +#### 18:00 - Closing diff --git a/data/v2/conferences/ocaml/2013/proposals/core-bench.pdf b/data/v2/conferences/ocaml/2013/proposals/core-bench.pdf new file mode 100644 index 0000000000..dc30f97944 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/core-bench.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/ctypes.pdf b/data/v2/conferences/ocaml/2013/proposals/ctypes.pdf new file mode 100644 index 0000000000..a823d1c91d Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/ctypes.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/formats-as-gadts.pdf b/data/v2/conferences/ocaml/2013/proposals/formats-as-gadts.pdf new file mode 100644 index 0000000000..1b3ffb83a6 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/formats-as-gadts.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/frenetic.pdf b/data/v2/conferences/ocaml/2013/proposals/frenetic.pdf new file mode 100644 index 0000000000..c82fb222f5 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/frenetic.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/goji.pdf b/data/v2/conferences/ocaml/2013/proposals/goji.pdf new file mode 100644 index 0000000000..53bac26d71 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/goji.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/gpgpu.pdf b/data/v2/conferences/ocaml/2013/proposals/gpgpu.pdf new file mode 100644 index 0000000000..cbc0bcc4dd Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/gpgpu.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/injectivity.pdf b/data/v2/conferences/ocaml/2013/proposals/injectivity.pdf new file mode 100644 index 0000000000..9b9095732d Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/injectivity.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/merlin.pdf b/data/v2/conferences/ocaml/2013/proposals/merlin.pdf new file mode 100644 index 0000000000..5d26738285 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/merlin.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/ocamlot.pdf b/data/v2/conferences/ocaml/2013/proposals/ocamlot.pdf new file mode 100644 index 0000000000..00ba3e235e Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/ocamlot.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/optimizations.pdf b/data/v2/conferences/ocaml/2013/proposals/optimizations.pdf new file mode 100644 index 0000000000..2735b77312 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/optimizations.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/platform.pdf b/data/v2/conferences/ocaml/2013/proposals/platform.pdf new file mode 100644 index 0000000000..3e0b1b4b85 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/platform.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/profiling-memory.pdf b/data/v2/conferences/ocaml/2013/proposals/profiling-memory.pdf new file mode 100644 index 0000000000..7a517290e5 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/profiling-memory.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/runtime-types.pdf b/data/v2/conferences/ocaml/2013/proposals/runtime-types.pdf new file mode 100644 index 0000000000..b8ff3eb063 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/runtime-types.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/weather-related-data.pdf b/data/v2/conferences/ocaml/2013/proposals/weather-related-data.pdf new file mode 100644 index 0000000000..acf78838b9 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/weather-related-data.pdf differ diff --git a/data/v2/conferences/ocaml/2013/proposals/wxocaml.pdf b/data/v2/conferences/ocaml/2013/proposals/wxocaml.pdf new file mode 100644 index 0000000000..3dffc9ed9a Binary files /dev/null and b/data/v2/conferences/ocaml/2013/proposals/wxocaml.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/bourgoin.pdf b/data/v2/conferences/ocaml/2013/slides/bourgoin.pdf new file mode 100644 index 0000000000..fd4f7fe227 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/bourgoin.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/bozman.pdf b/data/v2/conferences/ocaml/2013/slides/bozman.pdf new file mode 100644 index 0000000000..590f3045ea Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/bozman.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/canou.pdf b/data/v2/conferences/ocaml/2013/slides/canou.pdf new file mode 100644 index 0000000000..8d81d93d46 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/canou.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/carty.pdf b/data/v2/conferences/ocaml/2013/slides/carty.pdf new file mode 100644 index 0000000000..ee04687b97 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/carty.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/chambart.pdf b/data/v2/conferences/ocaml/2013/slides/chambart.pdf new file mode 100644 index 0000000000..a171be3322 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/chambart.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/garrigue.pdf b/data/v2/conferences/ocaml/2013/slides/garrigue.pdf new file mode 100644 index 0000000000..077b27b976 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/garrigue.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/guha.pdf b/data/v2/conferences/ocaml/2013/slides/guha.pdf new file mode 100644 index 0000000000..5629bdbe0a Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/guha.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/henry.pdf b/data/v2/conferences/ocaml/2013/slides/henry.pdf new file mode 100644 index 0000000000..d9b8a8d420 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/henry.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/james.pdf b/data/v2/conferences/ocaml/2013/slides/james.pdf new file mode 100644 index 0000000000..8f191f9148 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/james.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/lefessant.pdf b/data/v2/conferences/ocaml/2013/slides/lefessant.pdf new file mode 100644 index 0000000000..fac8c59c87 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/lefessant.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/leroy.pdf b/data/v2/conferences/ocaml/2013/slides/leroy.pdf new file mode 100644 index 0000000000..681a7f3a8c Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/leroy.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/madhavapeddy.pdf b/data/v2/conferences/ocaml/2013/slides/madhavapeddy.pdf new file mode 100644 index 0000000000..489f244f44 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/madhavapeddy.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/padioleau.pdf b/data/v2/conferences/ocaml/2013/slides/padioleau.pdf new file mode 100644 index 0000000000..3ff7330334 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/padioleau.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/sheets.pdf b/data/v2/conferences/ocaml/2013/slides/sheets.pdf new file mode 100644 index 0000000000..fb8b977de8 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/sheets.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/vaugon.pdf b/data/v2/conferences/ocaml/2013/slides/vaugon.pdf new file mode 100644 index 0000000000..56dbd5e646 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/vaugon.pdf differ diff --git a/data/v2/conferences/ocaml/2013/slides/white.pdf b/data/v2/conferences/ocaml/2013/slides/white.pdf new file mode 100644 index 0000000000..20256f1b51 Binary files /dev/null and b/data/v2/conferences/ocaml/2013/slides/white.pdf differ diff --git a/data/v2/conferences/ocaml/2013/talks/index.md b/data/v2/conferences/ocaml/2013/talks/index.md new file mode 100644 index 0000000000..d32ad2d1a6 --- /dev/null +++ b/data/v2/conferences/ocaml/2013/talks/index.md @@ -0,0 +1,3 @@ +OCaml 2013: submissions + + diff --git a/data/video-watch.yml b/data/video-watch.yml index 61a6bade0c..df504264fc 100644 --- a/data/video-watch.yml +++ b/data/video-watch.yml @@ -9,6 +9,18 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: A 'Melange' of Tooling Coming Together - Antonio Monteiro - FUN OCaml 2024 + description: "Antonio Monteiro's FUN OCaml 2024 talk recording!\r\n\r\n\r\nOverview + by Antonio:\r\n\r\nMelange is a new compiler for OCaml targeting JavaScript. Melange + codebases integrate with the OCaml Platform: install from OPAM, build with Dune, + preprocess with `ppxl..." + url: https://watch.ocaml.org/videos/watch/eff48eec-03be-479e-ad76-0c454e63b938 + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/0ca24226-7678-488c-bf80-ce348eb158af.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: A Case for Multi-Switch Constraints in OPAM description: "A Case for Multi-Switch Constraints in OPAM - by Fabrice Le Fessant (INRIA)\r\n\r\nPackage managers usually only deal with packages and their versions, @@ -194,6 +206,19 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: Building Incremental and Reproducible Data Pipelines - Patrick Ferris - + FUN OCaml 2024 + description: "Patrick Ferris's FUN OCaml 2024 talk recording!\r\n\r\nOverview by + Patrick:\r\n\r\nWe present the good and the bad of building a dataflow engine + in OCaml. The engine underpins a complex ecological analysis of avoided deforestation + projects in tropical moi..." + url: https://watch.ocaml.org/videos/watch/08223c1d-c6dc-4e73-b988-b58de2a407c6 + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/e4cd54aa-a313-4f8d-be51-d4a9538672d0.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: Casually talking about ReScript, OSS, and communities with Patrick Ecker description: "Patrick (@ryyppy) is working with OSS in ReScript and part of the core team\r\n\r\nIf you'd like to support the show for more content about OCaml, @@ -438,6 +463,18 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: Easy GADTs by Repeating Yourself - Eduardo Rafael - FUN OCaml 2024 + description: "Eduardo Rafael's FUN OCaml 2024 talk recording!\r\n\r\nOverview by + Eduardo:\r\n\r\n\r\nTraditionally GADT's are used for lightweight tasks as the + code complexity increases quite. I will be arguing that this is mostly a lack + of common \"design patterns\" and m..." + url: https://watch.ocaml.org/videos/watch/12959f82-f503-4e77-8940-208cf81a9c84 + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/508a8b3a-88f5-4406-ab79-878c9ba46b66.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: Effective Concurrency through Algebraic Effects description: "" url: https://watch.ocaml.org/videos/watch/e9f6c837-1435-4349-af0f-07d22d1c11ea @@ -613,6 +650,18 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: How the Multicore Garbage Collector works - Sudha Parimala - FUN OCaml 2024 + description: "Sudha's FUN OCaml 2024 talk recording!\r\n\r\nOverview by Sudha:\r\n\r\nIn + a first, OCaml 5.0 shipped with native support for parallelism and concurrency. + This was a multi-year effort by the Multicore team and the OCaml development team + that culminated in..." + url: https://watch.ocaml.org/videos/watch/316e573e-6622-46da-aa25-de81d4477ca7 + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/c79ab9b0-8d48-43df-b979-abdae746811a.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: Implementing an interval computation library for OCaml description: "Implementing an interval computation library for OCaml, by Jean-Marc Alliot, Charlie Vanaret, Jean-Baptiste Gotteland, Nicolas Durand and David Gianazza.\r\n\r\nIn @@ -717,6 +766,18 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: Learning OCaml with Tiny Code Xmas - Michael Dales - FUN OCaml 2024 + description: "Michael Dales's FUN OCaml 2024 talk recording!\r\n\r\nOverview by + Michael:\r\n\r\n\r\nEach year the demo community run Tiny Code Xmas - using fantasy + consoles like TIC-80 and PICO-8 to teach people to do retro graphics effects and + size coding. But I didn't ..." + url: https://watch.ocaml.org/videos/watch/55fff7e8-5aff-4150-a326-1c407e40817d + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/5cf07b59-eaf7-4604-98b2-bcb4f7530e1d.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: 'Learning OCaml: An Online Learning Centre for OCaml' description: "Learn OCaml: An Online Learning Center for OCaml, by Benjamin Canou, Gr\xE9goire Henry, \xC7agdas Bozman and Fabrice Le Fessant.\r\n\r\nWe present @@ -729,6 +790,18 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: Let Signals in OCaml - Rizo Isrof - FUN OCaml 2024 + description: "Rizo Isrof's FunOCaml 2024 talk recording!\r\n\r\nOverview by Rizo:\r\n\r\nSignals + and fine-grained reactivity are two popular concepts in the JavaScript world, + thanks to their simplicity, ergonomics and excellent performance. What are signals? + What is th..." + url: https://watch.ocaml.org/videos/watch/31a13898-6c5a-4c82-aab9-6dcb0d805e64 + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/2ccc22eb-8740-4f62-9710-1731b69c071a.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: Leveraging Formal Specifications to Generate Fuzzing Suites description: "When testing a library, developers typically first have to capture the semantics they want to check. They then write the code implementing these @@ -783,6 +856,19 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: Maybe OCaml Was the Friends We Made Along the Way - Dillon Mulroy - FUN OCaml + 2024 + description: "Dillon Mulroy's FUN OCaml 2024 talk recording!\r\n\r\nOverview by + Dillon:\r\n\r\nIn my decade-long journey as a software engineer, the most transformative + experience came from an unexpected source: learning and using OCaml. I will share + how this functiona..." + url: https://watch.ocaml.org/videos/watch/cebc2faf-3df3-4179-8ea8-64a50e1d84ff + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/da273a66-26d6-4419-b199-87a2890d38ec.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: 'Memo: an incremental computation library that powers Dune' description: "Memo: an incremental computation library that powers Dune\r\n\r\nAndrey Mokhov (Jane Street)\r\nArseniy Alekseyev (Jane Street)\r\n\r\nWe present Memo, @@ -795,6 +881,19 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: MirageOS - Developing Operating Systems in OCaml - Hannes Mehnert - FUN OCaml + 2024 + description: "Hannes Mehnert's FUN OCaml 2024 talk recording!\r\n\r\nOverview by + Hannes:\r\n\r\n\r\nOCaml is a great systems programming language. We use it since + more than a decade to develop MirageOS unikernels: run OCaml as a virtual machine, + no Linux kernel involved...." + url: https://watch.ocaml.org/videos/watch/3ad9fc58-ca49-4b2b-9278-fc980bcd7634 + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/2f3c5db2-5139-4835-87b4-3c1652bbb28c.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: Multicore OCaml description: "Multicore OCaml, by Stephen Dolan, Leo White, Anil Madhavapeddy (University of Cambridge).\r\n\r\nCurrently, threading is supported in OCaml only by means @@ -840,6 +939,18 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: OCANNL, the `neural_nets_lib` - Lukasz Stafiniak - FUN OCaml 2024 + description: "Lukasz Stafiniak's FUN OCaml 2024 talk recording!\r\n\r\nOverview + by Lukasz:\r\n\r\n\r\nUsing OCANNL, we will build a toy feed forward network, + we will train it, visualize its outputs. We will take a peek at the actual computation + generated at various level..." + url: https://watch.ocaml.org/videos/watch/f1af695d-21a5-45d1-ad05-ba4c87a106be + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/b944947f-5f5d-47f8-a9d0-25cb4d9dc3de.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: OCaml Companion Tools description: "OCaml Companion Tools, by Xavier Clerc.\r\n\r\nThe objective of this talk is to present several tools that aim to ease the development of software @@ -1028,6 +1139,18 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: Outreachy December 2024 Demo + description: "The OCaml community participated in the December 2024 round of [Outreachy + internships](https://www.outreachy.org). One intern worked on a tool for diffing + OCaml APIs.\r\n\r\nThis meeting was an opportunity for our intern to present their + work and for ..." + url: https://watch.ocaml.org/videos/watch/70ef58ff-ff7c-40d6-ab19-e886e4e98205 + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/9d342118-1e60-4653-b6a4-fc500d0ea002.jpg + published: 2025-04-17T09:45:05.088Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: Outreachy May 2024 Demo description: The OCaml community participated in the May 2024 round of [Outreachy](https://www.outreachy.org/) internships. Three interns worked on a range of projects including tools to diff @@ -1424,6 +1547,18 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: The Future of Dune - Leandro Ostera - FUN OCaml 2024 + description: "Leandro Ostera's FUN OCaml 2024 talk recording!\r\n\r\nOverview by + Leandro:\r\n\r\n\r\nIn this talk Leandro Ostera, the PM of OCaml Build System + team at Tarides shows the future of developer experience in dune. He will present + the new features that are bein..." + url: https://watch.ocaml.org/videos/watch/0cdb9fba-13d4-48fb-b06c-ea7a9583356d + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/5a4bfc62-e22b-4809-b7c9-925832cdc1c1.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: The ImpFS filesystem description: "This proposal describes a presentation to be given at the OCaml\u201920 workshop. The presentation will cover a new OCaml filesystem, ImpFS, and the related @@ -1529,6 +1664,19 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: The Story Behind the Fastest Image Comparison Library - Dmitriy Kovalenko + - FUN OCaml 2024 + description: "Dmitriy Kovalenko's FUN OCaml 2024 talk recording!\r\n\r\nOverview + by Dmitriy:\r\n\r\nI am the author of dmtrKovalenko/odiff which claims to be and + it is the fastest in the world (on my banchmarks lol) implementation of the pixel-by-pixel + image comparison..." + url: https://watch.ocaml.org/videos/watch/88a712b2-e800-4eee-bb16-e9710a9b5102 + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/c3501e6c-9fa7-4dec-924f-3f91473d771e.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: The final pieces of the OCaml documentation puzzle description: 'Rendering OCaml document is widely known as a very difficult task: The ever-evolving OCaml module system is extremely rich and can include complex @@ -1593,6 +1741,19 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: Type engineering in OCaml, Illustrated on the OCaml Compiler - Florian Angeletti + - FUN OCaml 2024 + description: "Florian Angeletti's FUN OCaml 2024 talk recording!\r\n\r\nOverview + by Florian:\r\n\r\n\r\nWith four different kinds of variants and four different + implementations of an object system, OCaml provides many options to design types + to fit domain problems. Howev..." + url: https://watch.ocaml.org/videos/watch/7a86d018-021f-4e9e-bb8c-7be05d7e378c + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/7cdb5bd4-5330-4ff0-8dce-17996c71e42c.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: Types in Amber description: Coda is a new cryptocurrency that uses zk-SNARKs to dramatically reduce the size of data needed by nodes running its protocol. Nodes communicate in a @@ -1605,6 +1766,18 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: Universal React in OCaml - David Sancho Moreno - FUN OCaml 2024 + description: "David Sancho Moreno's FUN OCaml 2024 talk recording!\r\n\r\nOverview + by David:\r\n\r\n\r\nserver-reason-react implements react-dom/server and some + of React's internals in OCaml. Its purpose is to natively render HTML markup from + the server for a Reason Reac..." + url: https://watch.ocaml.org/videos/watch/f74571dc-c1e5-43d2-9d7d-e723a2165d02 + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/39c48723-73cc-4011-bbe7-67e0392bfeed.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: Using Preferences to Tame your Package Manager description: "" url: https://watch.ocaml.org/videos/watch/43536918-a6e5-4a53-a680-bed527319e31 @@ -1614,6 +1787,19 @@ author_uri: https://watch.ocaml.org/ source_link: https://watch.ocaml.org/ source_title: Watch OCaml +- title: "Using odoc to Write Documentation - Paul-Elliot Angl\xE8s d'Auriac - FUN + OCaml 2024" + description: "Paul-Elliot Angl\xE8s d'Auriac's FUN OCaml 2024 talk recording!\r\n\r\nOverview + by Paul-Elliot:\r\n\r\nThis talk is a gentle introduction to the documenting part + of the OCaml ecosystem. We will see how to use `odoc` to build nice documentation + for your `dune..." + url: https://watch.ocaml.org/videos/watch/e844250f-a6c2-46aa-8d66-b9a436b6c8bc + thumbnail: https://watch.ocaml.org/lazy-static/thumbnails/aeba6eed-9e4f-44c4-a2f8-b7c6483fd609.jpg + published: 2024-11-20T00:00:00.000Z + author_name: Unknown + author_uri: https://watch.ocaml.org/ + source_link: https://watch.ocaml.org/ + source_title: Watch OCaml - title: Verifying an Effect-Based Cooperative Concurrency Scheduler in Iris by Adrian Dapprich description: "Lightweight asynchronous programming (using futures, goroutines or diff --git a/data/video-youtube.yml b/data/video-youtube.yml index b084f2ea1d..2cdd4cafdb 100644 --- a/data/video-youtube.yml +++ b/data/video-youtube.yml @@ -1,3 +1,28 @@ +- title: Making OCaml Safe for Performance Engineering + url: https://www.youtube.com/watch/g3qd4zpm1LA?version=3 + thumbnail: https://i4.ytimg.com/vi/g3qd4zpm1LA/hqdefault.jpg + description: "Jane Street is a trading firm that uses a variety of high-performance + systems built in OCaml to provide liquidity to financial markets worldwide. Over + the last couple of years, we have started developing major extensions to OCaml\u2019s + type system, with the primary goal of making OCaml a better language for writing + high-performance systems. In this talk, we will attempt to provide a developer's-eye + view of these changes. We\u2019ll cover two major directions of innovation: first, + the addition of modal types to OCaml, which opens up a variety of ambitious features, + like memory-safe stack-allocation; type-level tracking of effects, and data-race + freedom guarantees for multicore code. The second is the addition of a kind system + to OCaml, which provides more control over the representation of memory, in particular + allowing for structured data to be represented in a cache-and-prefetch-friendly + tabular form. Together, these features pull together some of the most important + features for writing high performance code in Rust, while maintaining the relative + simplicity of programming in OCaml. In all of this, we will focus less on the + type theory, and more on how these features are surfaced to users, the practical + problems that they help us solve, and the place in the design space of programming + languages that this leaves us in." + published: 2025-04-03T20:44:20+00:00 + author_name: Jane Street + author_uri: https://www.youtube.com/channel/UCDsVC_ewpcEW_AQcO-H-RDQ + source_link: https://www.youtube.com/feeds/videos.xml?playlist_id=PLCiAikFFaMJoWyXnJ2BWpse5HuiYibNYs + source_title: Jane Street - Tech Talks - title: Universal React in OCaml - David Sancho Moreno - FUN OCaml 2024 url: https://www.youtube.com/watch/Oy3lZl2kE-0?version=3 thumbnail: https://i4.ytimg.com/vi/Oy3lZl2kE-0/hqdefault.jpg @@ -72,7 +97,10 @@ Twitter: https://x.com/FunOCaml - Bluesky: https://bsky.app/profile/fun-ocaml.com' + Bluesky: https://bsky.app/profile/fun-ocaml.com + + + #ocaml' published: 2024-11-20T09:24:00+00:00 author_name: FUN OCaml author_uri: https://www.youtube.com/channel/UC3TI-fmhJ_g3_n9fHaXGZKA @@ -109,7 +137,10 @@ Twitter: https://x.com/FunOCaml - Bluesky: https://bsky.app/profile/fun-ocaml.com' + Bluesky: https://bsky.app/profile/fun-ocaml.com + + + #ocaml' published: 2024-11-20T09:24:00+00:00 author_name: FUN OCaml author_uri: https://www.youtube.com/channel/UC3TI-fmhJ_g3_n9fHaXGZKA @@ -143,7 +174,10 @@ Twitter: https://x.com/FunOCaml - Bluesky: https://bsky.app/profile/fun-ocaml.com' + Bluesky: https://bsky.app/profile/fun-ocaml.com + + + #ocaml' published: 2024-11-20T09:24:00+00:00 author_name: FUN OCaml author_uri: https://www.youtube.com/channel/UC3TI-fmhJ_g3_n9fHaXGZKA @@ -174,7 +208,10 @@ Twitter: https://x.com/FunOCaml - Bluesky: https://bsky.app/profile/fun-ocaml.com' + Bluesky: https://bsky.app/profile/fun-ocaml.com + + + #ocaml' published: 2024-11-20T09:23:58+00:00 author_name: FUN OCaml author_uri: https://www.youtube.com/channel/UC3TI-fmhJ_g3_n9fHaXGZKA @@ -207,7 +244,10 @@ Twitter: https://x.com/FunOCaml - Bluesky: https://bsky.app/profile/fun-ocaml.com' + Bluesky: https://bsky.app/profile/fun-ocaml.com + + + #ocaml' published: 2024-11-20T09:23:58+00:00 author_name: FUN OCaml author_uri: https://www.youtube.com/channel/UC3TI-fmhJ_g3_n9fHaXGZKA @@ -236,7 +276,10 @@ Twitter: https://x.com/FunOCaml - Bluesky: https://bsky.app/profile/fun-ocaml.com' + Bluesky: https://bsky.app/profile/fun-ocaml.com + + + #ocaml' published: 2024-11-20T09:23:58+00:00 author_name: FUN OCaml author_uri: https://www.youtube.com/channel/UC3TI-fmhJ_g3_n9fHaXGZKA @@ -307,7 +350,10 @@ Twitter: https://x.com/FunOCaml - Bluesky: https://bsky.app/profile/fun-ocaml.com' + Bluesky: https://bsky.app/profile/fun-ocaml.com + + + #ocaml' published: 2024-11-20T09:23:58+00:00 author_name: FUN OCaml author_uri: https://www.youtube.com/channel/UC3TI-fmhJ_g3_n9fHaXGZKA diff --git a/dune b/dune index 2a33239f6e..7997026488 100644 --- a/dune +++ b/dune @@ -3,22 +3,13 @@ (rule (target main.css) (deps - %{project_root}/tool/tailwind/tailwindcss (:config %{project_root}/tailwind.config.js) (:input %{project_root}/src/ocamlorg_frontend/css/styles.css) (source_tree %{project_root}/src/ocamlorg_frontend)) (action (chdir %{project_root} - (run - %{project_root}/tool/tailwind/tailwindcss - -m - -c - %{config} - -i - %{input} - -o - %{target}))))) + (run tailwindcss -m -c %{config} -i %{input} -o %{target}))))) (subdir asset/ diff --git a/dune-project b/dune-project index 5b6c970615..15fb213ca5 100644 --- a/dune-project +++ b/dune-project @@ -24,6 +24,9 @@ (using mdx 0.1) +(package + (name tailwindcss) (allow_empty)) + (package (name ocamlorg) (synopsis "Official OCaml website") @@ -67,6 +70,7 @@ olinkcheck ; tools/ood-gen ppx_deriving_yaml + ppx_import ppx_stable ezjsonm lambdasoup diff --git a/ocamlorg.opam b/ocamlorg.opam index 6290d70761..837e74a55d 100644 --- a/ocamlorg.opam +++ b/ocamlorg.opam @@ -45,6 +45,7 @@ depends: [ "mdx" {with-test & >= "1.10.0"} "olinkcheck" "ppx_deriving_yaml" + "ppx_import" "ppx_stable" "ezjsonm" "lambdasoup" diff --git a/src/ocamlorg_data/data.ml b/src/ocamlorg_data/data.ml index bcaae984b3..e45f35de70 100644 --- a/src/ocamlorg_data/data.ml +++ b/src/ocamlorg_data/data.ml @@ -20,7 +20,13 @@ end module Changelog = struct include Changelog - let get_by_slug slug = List.find_opt (fun x -> String.equal slug x.slug) all + let get_by_slug slug = + List.find_opt + (fun x -> + match x with + | Release x -> String.equal slug x.slug + | Post x -> String.equal slug x.slug) + all end module Code_example = struct @@ -152,9 +158,7 @@ module Paper = struct let get_by_slug slug = List.find_opt (fun x -> String.equal slug x.slug) all end -module Planet = struct - include Planet -end +module Planet = Planet module Release = struct include Release @@ -238,3 +242,5 @@ module Conference = struct let all = Conference.all let get_by_slug slug = List.find_opt (fun x -> String.equal slug x.slug) all end + +module V2 = V2 diff --git a/src/ocamlorg_data/data.mli b/src/ocamlorg_data/data.mli index 655415ad3f..a3d8d2ee6f 100644 --- a/src/ocamlorg_data/data.mli +++ b/src/ocamlorg_data/data.mli @@ -211,3 +211,5 @@ module Conference : sig val all : t list val get_by_slug : string -> t option end + +module V2 : module type of V2 diff --git a/src/ocamlorg_data/data_intf.ml b/src/ocamlorg_data/data_intf.ml index 87b57a0412..cd23216aea 100644 --- a/src/ocamlorg_data/data_intf.ml +++ b/src/ocamlorg_data/data_intf.ml @@ -1,18 +1,5 @@ module Academic_institution = struct - type location = { lat : float; long : float } [@@deriving of_yaml, show] - - let pp_ptime fmt t = - Format.pp_print_string fmt "Ptime.of_rfc3339 \""; - Ptime.pp_rfc3339 () fmt t; - Format.pp_print_string fmt - "\" |> function Ok (t, _, _) -> t | Error _ -> failwith \"RFC 3339\"" - - let pp_print_option pp fmt = function - | None -> Format.pp_print_string fmt "None" - | Some x -> - Format.pp_print_string fmt "Some ("; - pp fmt x; - Format.pp_print_string fmt ")" + type location = { lat : float; long : float } type course = { name : string; @@ -22,12 +9,11 @@ module Academic_institution = struct enrollment : string option; year : int option; description : string; - last_check : Ptime.t option; [@printer pp_print_option pp_ptime] + last_check : Ptime.t option; lecture_notes : bool; exercises : bool; video_recordings : bool; } - [@@deriving show] type t = { name : string; @@ -44,7 +30,6 @@ module Academic_institution = struct body_md : string; body_html : string; } - [@@deriving show] end module Academic_testimonial = struct @@ -55,7 +40,6 @@ module Academic_testimonial = struct publication : string; year : string; } - [@@deriving of_yaml, show] end module Blog = struct @@ -67,38 +51,23 @@ module Blog = struct only_ocaml : bool; disabled : bool; } - [@@deriving show] - - module Post = struct - type t = { - title : string; - url : string; - slug : string; - source : source; - description : string option; - authors : string list; - date : string; - preview_image : string option; - body_html : string; - } - [@@deriving show] - end + + type post = { + title : string; + url : string; + slug : string; + source : source; + description : string option; + authors : string list; + date : string; + preview_image : string option; + body_html : string; + } end module Book = struct - type difficulty = Beginner | Intermediate | Advanced [@@deriving show] - - let difficulty_of_string = function - | "beginner" -> Ok Beginner - | "intermediate" -> Ok Intermediate - | "advanced" -> Ok Advanced - | s -> Error (`Msg ("Unknown difficulty type: " ^ s)) - - let difficulty_of_yaml = function - | `String s -> difficulty_of_string s - | _ -> Error (`Msg "Expected a string for difficulty type") - - type link = { description : string; uri : string } [@@deriving of_yaml, show] + type difficulty = Beginner | Intermediate | Advanced + type link = { description : string; uri : string } type t = { title : string; @@ -116,11 +85,10 @@ module Book = struct body_md : string; body_html : string; } - [@@deriving show] end module Changelog = struct - type t = { + type release = { title : string; slug : string; date : string; @@ -129,12 +97,24 @@ module Changelog = struct body_html : string; body : string; authors : string list; + contributors : string list; + } + + type post = { + title : string; + slug : string; + date : string; + tags : string list; + body_html : string; + body : string; + authors : string list; } - [@@deriving of_yaml, show] + + type t = Release of release | Post of post end module Code_examples = struct - type t = { title : string; body : string } [@@deriving show] + type t = { title : string; body : string } end module Cookbook = struct @@ -143,7 +123,6 @@ module Cookbook = struct slug : string; subcategories : category list; } - [@@deriving show] type task = { title : string; @@ -151,17 +130,14 @@ module Cookbook = struct category_path : string list; description : string option; } - [@@deriving show] type code_block_with_explanation = { code : string; explanation : string } - [@@deriving show] type package = { name : string; tested_version : string; used_libraries : string list; } - [@@deriving of_yaml, show] type t = { slug : string; @@ -172,26 +148,11 @@ module Cookbook = struct code_plaintext : string; discussion_html : string; } - [@@deriving show] end module Event = struct type event_type = Meetup | Conference | Seminar | Hackathon | Retreat - [@@deriving show] - - let event_type_of_string = function - | "meetup" -> Ok Meetup - | "conference" -> Ok Conference - | "seminar" -> Ok Seminar - | "hackathon" -> Ok Hackathon - | "retreat" -> Ok Retreat - | s -> Error (`Msg ("Unknown event type: " ^ s)) - - let event_type_of_yaml = function - | `String s -> event_type_of_string s - | _ -> Error (`Msg "Expected a string for difficulty type") - - type location = { lat : float; long : float } [@@deriving of_yaml, show] + type location = { lat : float; long : float } type recurring_event = { title : string; @@ -202,10 +163,8 @@ module Event = struct location : location option; event_type : event_type; } - [@@deriving of_yaml, show] type utc_datetime = { yyyy_mm_dd : string; utc_hh_mm : string option } - [@@deriving of_yaml, show] type t = { title : string; @@ -223,21 +182,10 @@ module Event = struct recurring_event : recurring_event option; event_type : event_type; } - [@@deriving show] end module Exercise = struct - type difficulty = Beginner | Intermediate | Advanced [@@deriving show] - - let of_string = function - | "beginner" -> Ok Beginner - | "intermediate" -> Ok Intermediate - | "advanced" -> Ok Advanced - | s -> Error (`Msg ("Unknown difficulty type: " ^ s)) - - let difficulty_of_yaml = function - | `String s -> of_string s - | _ -> Error (`Msg "Expected a string for difficulty type") + type difficulty = Beginner | Intermediate | Advanced type t = { title : string; @@ -249,42 +197,12 @@ module Exercise = struct solution : string; tutorials : string list; } - [@@deriving show] end module Governance = struct - module Member = struct - type t = { name : string; github : string; role : string } - [@@deriving of_yaml, show] - - let compare a b = String.compare a.github b.github - end - - type contact_kind = GitHub | Email | Discord | Chat [@@deriving show] - - let contact_kind_of_yaml = function - | `String "github" -> Ok GitHub - | `String "email" -> Ok Email - | `String "discord" -> Ok Discord - | `String "chat" -> Ok Chat - | x -> ( - match Yaml.to_string x with - | Ok str -> - Error - (`Msg - ("\"" ^ str - ^ "\" is not a valid contact_kind! valid options are: github, \ - email, discord, chat")) - | Error _ -> Error (`Msg "Invalid Yaml value")) - - let contact_kind_to_yaml = function - | GitHub -> `String "github" - | Email -> `String "email" - | Discord -> `String "discord" - | Chat -> `String "chat" - + type member = { name : string; github : string; role : string } + type contact_kind = GitHub | Email | Discord | Chat type contact = { name : string; link : string; kind : contact_kind } - [@@deriving of_yaml, show] type dev_meeting = { date : string; @@ -293,18 +211,16 @@ module Governance = struct calendar : string option; notes : string; } - [@@deriving of_yaml, show] type team = { id : string; name : string; description : string; contacts : contact list; - dev_meeting : dev_meeting option; [@default None] [@key "dev-meeting"] - members : Member.t list; [@default []] - subteams : team list; [@default []] + dev_meeting : dev_meeting option; + members : member list; + subteams : team list; } - [@@deriving of_yaml, show] end module Industrial_user = struct @@ -320,15 +236,11 @@ module Industrial_user = struct body_md : string; body_html : string; } - [@@deriving show] end module Is_ocaml_yet = struct type external_package = { url : string; synopsis : string } - [@@deriving of_yaml, show] - type package = { name : string; extern : external_package option } - [@@deriving of_yaml, show] type category = { name : string; @@ -337,7 +249,6 @@ module Is_ocaml_yet = struct packages : package list; slug : string; } - [@@deriving show] type t = { id : string; @@ -346,7 +257,6 @@ module Is_ocaml_yet = struct categories : category list; body_html : string; } - [@@deriving show] end module Job = struct @@ -358,7 +268,6 @@ module Job = struct company : string; company_logo : string; } - [@@deriving of_yaml, show] end module Testimonial = struct @@ -369,7 +278,6 @@ module Testimonial = struct role : string; logo : string; } - [@@deriving of_yaml, show] end module News = struct @@ -382,7 +290,6 @@ module News = struct body_html : string; authors : string list; } - [@@deriving show] end module Opam_user = struct @@ -392,7 +299,6 @@ module Opam_user = struct github_username : string option; avatar : string option; } - [@@deriving of_yaml, show] end module Outreachy = struct @@ -405,9 +311,8 @@ module Outreachy = struct mentors : string list; video : string option; } - [@@deriving of_yaml, show] - type t = { name : string; projects : project list } [@@deriving of_yaml, show] + type t = { name : string; projects : project list } end module Page = struct @@ -420,11 +325,10 @@ module Page = struct body_md : string; body_html : string; } - [@@deriving show] end module Paper = struct - type link = { description : string; uri : string } [@@deriving of_yaml, show] + type link = { description : string; uri : string } type t = { title : string; @@ -437,19 +341,10 @@ module Paper = struct links : link list; featured : bool; } - [@@deriving show] end module Release = struct - type kind = [ `Compiler ] [@@deriving show] - - let kind_of_string = function - | "compiler" -> Ok `Compiler - | s -> Error (`Msg ("Unknown release type: " ^ s)) - - let kind_of_yaml = function - | `String s -> kind_of_string s - | _ -> Error (`Msg "Expected a string for release type") + type kind = [ `Compiler ] type t = { kind : kind; @@ -464,7 +359,6 @@ module Release = struct body_md : string; body_html : string; } - [@@deriving show] end module Resource = struct @@ -476,7 +370,6 @@ module Resource = struct source_url : string option; featured : bool; } - [@@deriving of_yaml, show] end module Success_story = struct @@ -494,23 +387,10 @@ module Success_story = struct body_md : string; body_html : string; } - [@@deriving show] end module Tool = struct type lifecycle = [ `Incubate | `Active | `Sustain | `Deprecate ] - [@@deriving show] - - let lifecycle_of_string = function - | "incubate" -> Ok `Incubate - | "active" -> Ok `Active - | "sustain" -> Ok `Sustain - | "deprecate" -> Ok `Deprecate - | s -> Error (`Msg ("Unknown lifecycle type: " ^ s)) - - let lifecycle_of_yaml = function - | `String s -> lifecycle_of_string s - | _ -> Error (`Msg "Expected a string for lifecycle type") type t = { name : string; @@ -521,15 +401,11 @@ module Tool = struct description : string; lifecycle : lifecycle; } - [@@deriving show] end module Tool_page = struct type toc = { title : string; href : string; children : toc list } - [@@deriving of_yaml, show] - type contribute_link = { url : string; description : string } - [@@deriving of_yaml, show] type t = { title : string; @@ -542,42 +418,23 @@ module Tool_page = struct toc : toc list; body_html : string; } - [@@deriving show] end module Tutorial = struct - module Section = struct - type t = GetStarted | Language | Platform | Guides [@@deriving show] - - let of_string = function - | "getting-started" -> Ok GetStarted - | "language" -> Ok Language - | "platform" -> Ok Platform - | "guides" -> Ok Guides - | s -> Error (`Msg ("Unknown section: " ^ s)) - end - + type section = GetStarted | Language | Platform | Guides type toc = { title : string; href : string; children : toc list } - [@@deriving show] - type contribute_link = { url : string; description : string } - [@@deriving of_yaml, show] - type banner = { image : string; url : string; alt : string } - [@@deriving of_yaml, show] type external_tutorial = { tag : string; banner : banner; contribute_link : contribute_link; } - [@@deriving of_yaml, show] - - type recommended_next_tutorials = string list [@@deriving of_yaml, show] - type prerequisite_tutorials = string list [@@deriving of_yaml, show] + type recommended_next_tutorials = string list + type prerequisite_tutorials = string list type search_document_section = { title : string; id : string } - [@@deriving show] type search_document = { title : string; @@ -586,7 +443,6 @@ module Tutorial = struct content : string; slug : string; } - [@@deriving show] type t = { title : string; @@ -594,7 +450,7 @@ module Tutorial = struct fpath : string; slug : string; description : string; - section : Section.t; + section : section; category : string; external_tutorial : external_tutorial option; body_md : string; @@ -603,7 +459,6 @@ module Tutorial = struct recommended_next_tutorials : recommended_next_tutorials; prerequisite_tutorials : prerequisite_tutorials; } - [@@deriving show] end module Video = struct @@ -611,30 +466,18 @@ module Video = struct title : string; url : string; thumbnail : string; - description : string; [@default ""] + description : string; published : string; author_name : string; author_uri : string; source_link : string; source_title : string; } - [@@deriving yaml, show] end module Conference = struct - type role = [ `Co_chair | `Chair ] [@@deriving show] - - let role_of_string = function - | "chair" -> Ok `Chair - | "co-chair" -> Ok `Co_chair - | s -> Error (`Msg ("Unknown role type: " ^ s)) - - let role_of_yaml = function - | `String s -> role_of_string s - | _ -> Error (`Msg "Expected a string for role type") - + type role = [ `Co_chair | `Chair ] type important_date = { date : string; info : string } - [@@deriving of_yaml, show] type committee_member = { name : string; @@ -642,18 +485,17 @@ module Conference = struct affiliation : string option; picture : string option; } - [@@deriving of_yaml, show] type presentation = { title : string; authors : string list; link : string option; - video : string option; + watch_ocamlorg_video : string option; + youtube_video : string option; slides : string option; poster : bool; additional_links : string list; } - [@@deriving of_yaml, show] type t = { title : string; @@ -667,15 +509,10 @@ module Conference = struct body_md : string; body_html : string; } - [@@deriving of_yaml, show] end (* Depends on Video and Blog modules to define the different kinds of entries of the OCaml Planet *) module Planet = struct - type entry = BlogPost of Blog.Post.t | Video of Video.t [@@deriving show] - - let date_of_post = function - | BlogPost { date; _ } -> date - | Video { published; _ } -> published + type entry = BlogPost of Blog.post | Video of Video.t end diff --git a/src/ocamlorg_data/dune b/src/ocamlorg_data/dune index ac90548237..befc1ea06d 100644 --- a/src/ocamlorg_data/dune +++ b/src/ocamlorg_data/dune @@ -340,3 +340,22 @@ (with-stdout-to %{target} (run %{ood_gen} conferences))))) + +(rule + (target v2.ml) + (deps + (:v2 + (source_tree %{workspace_root}/data/v2))) + (action + (chdir + %{workspace_root}/data/v2 + (with-stdout-to + %{target} + (progn + (echo "let assets = [\n") + (pipe-stdout + (run find . -type f) + (run cut -b 2-) + (run sed "s/^/ \"/") + (run sed "s/$/\";/")) + (echo "]\n")))))) diff --git a/src/ocamlorg_frontend/components/icons.eml b/src/ocamlorg_frontend/components/icons.eml index f1adcb17a7..6fe38a63a7 100644 --- a/src/ocamlorg_frontend/components/icons.eml +++ b/src/ocamlorg_frontend/components/icons.eml @@ -51,7 +51,12 @@ let calendar class_ = -let changelog class_ = +let changelog_release class_ = + + +let changelog_post class_ = diff --git a/src/ocamlorg_frontend/components/navmap.eml b/src/ocamlorg_frontend/components/navmap.eml index cf56383fa8..20c4a0457e 100644 --- a/src/ocamlorg_frontend/components/navmap.eml +++ b/src/ocamlorg_frontend/components/navmap.eml @@ -28,11 +28,12 @@ let kind_title = function | Class_type -> "Class type" | _ -> "?" -let title_style = "flex-1 flex-nowrap py-1 md:py-0.5 pr-1 text-title dark:text-dark-title" +let title_style = "flex-1 flex-nowrap py-1 md:py-0.5 pr-1 text-title dark:text-dark-title truncate" -let htmx_attributes = "hx-boost=\"true\" hx-ext=\"multi-swap\" hx-swap=\"multi:#htmx-head,#htmx-sidebar,#htmx-content,#htmx-right-sidebar,#htmx-breadcrumbs\" hx-push-url=\"true\"" +let htmx_attributes = "hx-boost=\"true\" hx-ext=\"multi-swap\" hx-swap=\"multi:#htmx-head,#htmx-content,#htmx-right-sidebar,#htmx-breadcrumbs\" hx-push-url=\"true\"" let icon_style = function + | Page -> "navmap-tag page-tag" | Library -> "navmap-tag library-tag" | Module -> "navmap-tag module-tag" | Module_type -> "navmap-tag module-type-tag" @@ -75,20 +76,20 @@ let rec nested_render ~path (item : toc) = let active_style = if item.title = fragment then (if List.length path = 0 then "bg-gray-200 dark:bg-dark-tertiary_bt_hover font-medium dark:font-semibold" else "border-transparent bg-gray-100 dark:bg-dark-tertiary_bt_hover font-medium dark:font-semibold") else "border-transparent" in
}">
-
"> +
"> <%s icon_style item.kind %>"> <% (match item.href with | None -> %> "> <%s! item.title %> - <%s! Icons.chevron_down "h-5 w-5" %> + <%s! Icons.chevron_down "h-5 w-5" %> <% | Some href -> %> class="<%s title_style %> overflow-hidden truncate text-title dark:text-dark-title transition-colors hover:text-primary"> <%s! item.title %> - + <% ); %>
diff --git a/src/ocamlorg_frontend/components/package_breadcrumbs.eml b/src/ocamlorg_frontend/components/package_breadcrumbs.eml index 8c43612933..7a9b0751a9 100644 --- a/src/ocamlorg_frontend/components/package_breadcrumbs.eml +++ b/src/ocamlorg_frontend/components/package_breadcrumbs.eml @@ -1,30 +1,33 @@ -type library_path_item = - | Module of { name: string; href: string; } - | ModuleType of { name: string; href: string; } - | Parameter of { name: string; href: string; number: int; } - | Class of { name: string; href: string; } - | ClassType of { name: string; href: string; } +type breadcrumb = { + name: string; + href: string option; +} -type docs_path = - | Index - | Page of string - | Library of string * library_path_item list +type path_item = + | Module of breadcrumb + | ModuleType of breadcrumb + | Parameter of breadcrumb * int + | Class of breadcrumb + | ClassType of breadcrumb + | Page of breadcrumb -let kind_tag (m : library_path_item) = match m with +let kind_tag (m : path_item) = match m with | Module _ -> Module | ModuleType _ -> Module type - | Parameter { number; _ } -> + | Parameter (_, number) -> " class="breadcrumbs-tag parameter-tag"><%s "Parameter #" ^ (Int.to_string number) %> | Class _ -> Class | ClassType _ -> Class type + | Page _ -> + Page type path = | Overview of string option - | Documentation of (docs_path) + | Documentation of path_item list let render_package_and_version ~path @@ -57,54 +60,49 @@ let render_package_and_version
-type breadcrumb = { - name: string; - href: string; -} +let path_item_to_breadcrumb = function + | Module x | ModuleType x | Class x | ClassType x | Parameter (x, _) | Page x + -> + x -let library_path_item_to_breadcrumb = function - | Module x -> { name = x.name; href = x.href } - | ModuleType x -> { name = x.name; href = x.href } - | Class x -> { name = x.name; href = x.href } - | ClassType x -> { name = x.name; href = x.href } - | Parameter x -> { name = x.name; href = x.href } +let is_page : path_item -> bool = function Page _ -> true | _ -> false -let render_library_path_breadcrumbs -~library_name -~(path: library_path_item list) = - let render_breadcrumb i b = - if i < List.length path - 1 then - <%s b.name %> - else - <%s b.name %> +let render_path_breadcrumbs +~(path: path_item list) = + let pages, modules = List.partition is_page path in + let render_breadcrumb max i b = + match b.href with + | None when i < max -> + <%s b.name %> + | None -> + <%s b.name %> + | Some href when i < max -> + <%s b.name %> + | Some href -> + <%s b.name %> in -
  • - <%s library_name %> lib -
  • -
  • - <%s! String.concat "." (path |> List.map library_path_item_to_breadcrumb |> List.mapi render_breadcrumb); %> - <%s! kind_tag (List.hd (List.rev path)) %> -
  • + let li content = +
  • + <%s! content %> +
  • + in + let page_items = List.fold_left (fun (i, acc) item -> + (i+1, acc ^ li (render_breadcrumb (List.length pages - 1) i (path_item_to_breadcrumb item)))) (0,"") pages |> snd in + let ms = + <%s! String.concat "." (List.mapi (render_breadcrumb (List.length modules - 1)) (List.map path_item_to_breadcrumb modules)) %> + in + let last = kind_tag (List.hd (List.rev path)) in + if List.length modules > 0 then + page_items ^ li (ms ^ last) + else + page_items let render_docs_path_breadcrumbs -~(path: docs_path) -(package: Package.package) +~(path: path_item list) = - let version = Package.url_version package in @@ -122,8 +120,7 @@ let render_overview_breadcrumbs let render ~(path: path) -(package: Package.package) = match path with | Overview page -> render_overview_breadcrumbs page - | Documentation (docs_path) -> render_docs_path_breadcrumbs ~path:docs_path package + | Documentation (docs_path) -> render_docs_path_breadcrumbs ~path:docs_path diff --git a/src/ocamlorg_frontend/layouts/package_layout.eml b/src/ocamlorg_frontend/layouts/package_layout.eml index 4f95ededfe..a8bf7b568b 100644 --- a/src/ocamlorg_frontend/layouts/package_layout.eml +++ b/src/ocamlorg_frontend/layouts/package_layout.eml @@ -199,7 +199,7 @@ Layout.base let list_item = document.createElement("li"); let a = document.createElement("a"); - let href = "/" + entry.url; + let href = entry.url; a.href = href; a.id = "search-result-"+entry.id; a.classList.add("search-entry", kind.innerText.slice(0,3)); diff --git a/src/ocamlorg_frontend/pages/academic_institutions.eml b/src/ocamlorg_frontend/pages/academic_institutions.eml index 33621e889e..2342df9221 100644 --- a/src/ocamlorg_frontend/pages/academic_institutions.eml +++ b/src/ocamlorg_frontend/pages/academic_institutions.eml @@ -29,7 +29,7 @@ Layout.render

    30+ Academic Entries

    -

    To list an academic institution, check out the Contributing Guide on GitHub.

    +

    To list an academic institution, check out the Contributing Guide on GitHub.

    <%s! Forms.search_input ~name:"q" diff --git a/src/ocamlorg_frontend/pages/changelog.eml b/src/ocamlorg_frontend/pages/changelog.eml index 5c7e7bf035..4490dde96e 100644 --- a/src/ocamlorg_frontend/pages/changelog.eml +++ b/src/ocamlorg_frontend/pages/changelog.eml @@ -1,3 +1,65 @@ +let render_changelog_entry ?current_tag (item: Data.Changelog.t) = match item with + | Release item -> +
    +
    +
    + +

    + <%s item.title %> +

    + + <% (match item.tags with [] -> () | _ -> %> +
    + <% item.tags |> List.iter (fun tag -> %> + "><%s tag %> + <% ); %> +
    + <% ); %> +
    +
    +
    +
    + <%s! item.body_html %> + <% (match item.changelog_html with | None -> () | Some changelog -> %> +
    + See full changelog + <%s! changelog %> +
    + <% ); %> +
    +
    +
    + | Post item -> +
    +
    +
    + +

    + <%s item.title %> +

    + + <% (match item.tags with [] -> () | _ -> %> +
    + <% item.tags |> List.iter (fun tag -> %> + "><%s tag %> + <% ); %> +
    + <% ); %> +
    +
    +
    +
    + <%s! item.body_html %> +
    +
    +
    + let render ~tags ?current_tag ~(pagination_info : Pagination.t) (news : Data.Changelog.t list) = News_layout.single_column_layout ~title:"OCaml Changelog" @@ -16,7 +78,7 @@ News_layout.single_column_layout
    -

    Read the latest releases and updates from the OCaml ecosystem.

    +

    Read the latest releases and updates from the OCaml compiler, OCaml infrastructure and the OCaml Platform Tools.

    @@ -55,40 +117,7 @@ News_layout.single_column_layout
    - <% news |> List.iter (fun (item : Data.Changelog.t) -> %> - - <% ); %> + <%s! news |> List.map (fun (item : Data.Changelog.t) -> render_changelog_entry ?current_tag item ) |> String.concat "" %> <%s! Pagination.render pagination_info %>
    diff --git a/src/ocamlorg_frontend/pages/changelog_entry.eml b/src/ocamlorg_frontend/pages/changelog_entry.eml index b197a2d1f8..cb1b1cc55e 100644 --- a/src/ocamlorg_frontend/pages/changelog_entry.eml +++ b/src/ocamlorg_frontend/pages/changelog_entry.eml @@ -1,52 +1,99 @@ -let render (change : Data.Changelog.t) = -Layout.render -~title:(Printf.sprintf "%s • OCaml Changelog" change.title) -~description:change.title @@ -
    -
    -
    +let render (entry : Data.Changelog.t) = match entry with +| Release release -> + Layout.render + ~title:(Printf.sprintf "%s • OCaml Changelog" release.title) + ~description:release.title @@ +
    +
    + -
    -

    - <%s change.title %> -

    - <% (match change.tags with [] -> () | _ -> %> -
      - <% change.tags |> List.iter (fun tag -> %> -
    • - - <%s tag %> - -
    • +
      +

      + <%s release.title %> +

      + <% (match release.tags with [] -> () | _ -> %> +
        + <% release.tags |> List.iter (fun tag -> %> +
      • + + <%s tag %> + +
      • + <% ); %> +
      <% ); %> -
    - <% ); %> -
    + -
    - -
    - <%s! change.body_html %> - <% (match change.changelog_html with | None -> () | Some changelog -> %> -
    - See full changelog - <%s! changelog %> -
    - <% ); %> -
    -
    +
    + +
    + <%s! release.body_html %> + <% (match release.changelog_html with | None -> () | Some changelog -> %> +
    + See full changelog + <%s! changelog %> +
    + <% ); %> +
    +
    +
    -
    \ No newline at end of file +| Post post -> + Layout.render + ~title:(Printf.sprintf "%s • OCaml Changelog" post.title) + ~description:post.title @@ +
    +
    +
    + + +
    +

    + <%s post.title %> +

    + <% (match post.tags with [] -> () | _ -> %> + + <% ); %> +
    + +
    + +
    + <%s! post.body_html %> +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/src/ocamlorg_frontend/pages/community.eml b/src/ocamlorg_frontend/pages/community.eml index c86cd0a1b7..99f945bca1 100644 --- a/src/ocamlorg_frontend/pages/community.eml +++ b/src/ocamlorg_frontend/pages/community.eml @@ -67,7 +67,7 @@ Community_layout.single_column_layout

    Video

    <%s! social_list_item ~text:("Community videos such as previous OCaml Conference presentation - ") ~href:("https://watch.ocaml.org/videos/recently-added") ~left_icon:(Icons.peertube "w-10 h-10") ~title:("Watch") "" %> <%s! social_list_item ~text:("Live Streams about OCaml - ") ~href:("https://twitch.tv/search?term=ocaml") ~left_icon:(Icons.twitch "w-10 h-10") ~title:("Twitch") "" %> - <%s! social_list_item ~text:("OCaml on YouTube - ") ~href:("https://www.youtube.com/results?search_query=OCaml") ~left_icon:(Icons.youtube "w-10 h-10") ~title:("YouTube") "" %> + <%s! social_list_item ~text:("OCaml on YouTube - ") ~href:("https://www.youtube.com/@OCamlLang") ~left_icon:(Icons.youtube "w-10 h-10") ~title:("YouTube") "" %>

      Microblogging

      @@ -81,7 +81,7 @@ Community_layout.single_column_layout

      Mailing Lists

      - <%s! social_list_item ~text:("Share experience, exchange ideas and code, and report on applications - ") ~href:("https://inbox.vuxu.org/caml-list") ~left_icon:(Icons.email "w-10 h-10") ~title:("Caml User's Mailing List") "" %> + <%s! social_list_item ~text:("Share experience, exchange ideas and code, and report on applications - ") ~href:("https://inbox.ci.dev/caml-list") ~left_icon:(Icons.email "w-10 h-10") ~title:("Caml User's Mailing List") "" %>
    diff --git a/src/ocamlorg_frontend/pages/conference.eml b/src/ocamlorg_frontend/pages/conference.eml index 0cd4cb0c9b..e2a17ead7e 100644 --- a/src/ocamlorg_frontend/pages/conference.eml +++ b/src/ocamlorg_frontend/pages/conference.eml @@ -89,7 +89,10 @@ Community_layout.single_column_layout <% (match presentation.link with None -> () | Some link -> %> <%s! resource_link ~link (Icons.link "h-6 w-6") "Details" %> <% ); %> - <% (match presentation.video with None -> () | Some link -> %> + <% (match presentation.youtube_video with None -> () | Some link -> %> + <%s! resource_link ~link (Icons.youtube "h-6 w-6") "View on YouTube" %> + <% ); %> + <% (match presentation.watch_ocamlorg_video with None -> () | Some link -> %> <%s! resource_link ~link (Icons.video "h-6 w-6") "View Video" %> <% ); %> <% (match presentation.slides with None -> () | Some link -> %> @@ -106,6 +109,7 @@ Community_layout.single_column_layout
    +<% if conference.program_committee <> [] then ( %>

    Conference Details

    @@ -132,22 +136,57 @@ Community_layout.single_column_layout
    -<% let videos = List.filter (fun (p : Data.Conference.presentation) -> Option.is_some p.video) +<% ); %> + +<% if conference.organising_committee <> [] then ( %> +
    +
    +

    Conference Details

    +

    Organisers

    +
    + <% + let committee_with_pictures = List.filter (fun (x : Data.Conference.committee_member) -> Option.is_some x.picture) conference.organising_committee in + let committee_without_pictures = List.filter (fun (x : Data.Conference.committee_member) -> Option.is_none x.picture) conference.organising_committee in + let names = List.map (fun (x : Data.Conference.committee_member) -> match x.affiliation with None -> (x.name, "") | Some affiliation -> (x.name, affiliation)) committee_without_pictures in + committee_with_pictures |> List.iter (fun (member : Data.Conference.committee_member) -> %> +
    + +
    <%s member.name %>
    + <% (match member.affiliation with None -> () | Some affiliation -> %> +
    <%s affiliation %>
    + <% ); %> +
    + <% ); %> +
    +
      + <% names |> List.iter (fun (name, affiliation) -> %> +
    • <%s name %> + <% (match affiliation with "" -> () | _ -> %> + (<%s affiliation %>) + <% ); %> +

    • + <% ); %> +
    +
    +
    +<% ); %> + +<% let videos = List.filter (fun (p : Data.Conference.presentation) -> Option.is_some p.watch_ocamlorg_video) conference.presentations in (match List.length videos with | 0 -> () | _ -> %>

    Some Videos

    - <% let videos = List.filteri (fun i _ -> i < 6) videos in videos |> List.iter (fun (video : Data.Conference.presentation) -> %> + <% let videos = List.filteri (fun i _ -> i < 6) videos in videos |> List.iter (fun (presentation : Data.Conference.presentation) -> %>
    -
    <%s video.title %>
    +
    <%s presentation.title %>
    <% ); %>
    diff --git a/src/ocamlorg_frontend/pages/governance.eml b/src/ocamlorg_frontend/pages/governance.eml index a318ef51cb..7245c96dcc 100644 --- a/src/ocamlorg_frontend/pages/governance.eml +++ b/src/ocamlorg_frontend/pages/governance.eml @@ -1,4 +1,4 @@ -module MemberSet = Set.Make (Data.Governance.Member) +module MemberSet = Set.Make (struct type t = Data.Governance.member let compare a b = let open Data.Governance in String.compare a.github b.github end) let count_members (team : Data.Governance.team) = MemberSet.cardinal (MemberSet.of_list (team.members @ List.concat (List.map (fun (team : Data.Governance.team) -> team.members) team.subteams))) @@ -75,4 +75,4 @@ and what makes it unique." @@ " alt="camel head illustration">
    -
    \ No newline at end of file + diff --git a/src/ocamlorg_frontend/pages/governance_team.eml b/src/ocamlorg_frontend/pages/governance_team.eml index 6c1d38b681..ba1cf1f160 100644 --- a/src/ocamlorg_frontend/pages/governance_team.eml +++ b/src/ocamlorg_frontend/pages/governance_team.eml @@ -4,7 +4,7 @@ let contact_icon (kind : Data.Governance.contact_kind) = match kind with | Discord -> Icons.discord | Chat -> Icons.chat -let render_team_member (member : Data.Governance.Member.t) = +let render_team_member (member : Data.Governance.member) =
    @@ -58,7 +58,7 @@ let render_subteam (team : Data.Governance.team) =
    <% ); %>
    - <%s! team.members |> List.map (fun (member : Data.Governance.Member.t) -> render_team_member member ) |> String.concat "\n" %> + <%s! team.members |> List.map (fun (member : Data.Governance.member) -> render_team_member member ) |> String.concat "\n" %>
    @@ -107,7 +107,7 @@ Layout.render

    People

    - <%s! t.members |> List.map (fun (member : Data.Governance.Member.t) -> render_team_member member ) |> String.concat "\n" %> + <%s! t.members |> List.map (fun (member : Data.Governance.member) -> render_team_member member ) |> String.concat "\n" %>
    <% ); %> diff --git a/src/ocamlorg_frontend/pages/home.eml b/src/ocamlorg_frontend/pages/home.eml index f802e43606..5ec47294cc 100644 --- a/src/ocamlorg_frontend/pages/home.eml +++ b/src/ocamlorg_frontend/pages/home.eml @@ -12,6 +12,48 @@ let package_card ~href ~img_path ~name description =
    +let render_small_changelog_entry (item : Data.Changelog.t) = match item with + | Release item -> +
    +
    +
    +
    +
    + <%s! Icons.changelog_release "w-6 h-6" %> +
    + <%s item.title %> + +
    +

    + <%s! String.sub item.body 0 (min (String.length item.body - 1) 100) %>... +

    + + See full changelog + +
    +
    +
    + | Post item -> +
    +
    +
    +
    +
    + <%s! Icons.changelog_post "w-6 h-6" %> +
    + <%s item.title %> + +
    +

    + <%s! String.sub item.body 0 (min (String.length item.body - 1) 100) %>... +

    + + See full changelog + +
    +
    +
    + let render ~(latest_release: Data.Release.t) ~(lts_release: Data.Release.t) @@ -295,28 +337,9 @@ Layout.render Compiler and Platform Tools - <% let changelogs_length = List.length changelogs in changelogs |> - List.iteri (fun index (item : Data.Changelog.t) -> %> -
    "> -
    -
    -
    -
    - <%s! Icons.changelog "w-6 h-6" %> -
    - <%s item.title %> - -
    -

    - <%s! String.sub item.body 0 (min (String.length item.body - 1) 100) %>... -

    - - See full changelog - -
    -
    -
    - <% ); %> + <%s! changelogs + |> List.map (fun (item : Data.Changelog.t) -> render_small_changelog_entry item ) + |> String.concat "" %> See Full Changelog <%s! Icons.chevron_right "h-5 w-5" %> diff --git a/src/ocamlorg_frontend/pages/industrial_businesses.eml b/src/ocamlorg_frontend/pages/industrial_businesses.eml index b25a268326..cb5a6d914d 100644 --- a/src/ocamlorg_frontend/pages/industrial_businesses.eml +++ b/src/ocamlorg_frontend/pages/industrial_businesses.eml @@ -23,7 +23,7 @@ Layout.render

    Other Industry Users of OCaml

    With its strong security features and high performance, several companies rely on OCaml to keep their data operating both safely and efficiently. On this page, you can get an overview of the companies in the community and learn more about how they use OCaml.

    -

    If you want to contribute to add a new industrial user, check out the Contributing Guide on GitHub.

    +

    If you want to contribute to add a new industrial user, check out the Contributing Guide on GitHub.

    <% businesses |> List.iter (fun (item : Data.Industrial_user.t) -> let logo = match item.logo with | Some x -> Ocamlorg_static.Media.url x | None -> "" in %>
    diff --git a/src/ocamlorg_frontend/pages/industrial_users.eml b/src/ocamlorg_frontend/pages/industrial_users.eml index bef846dfd5..72958d5498 100644 --- a/src/ocamlorg_frontend/pages/industrial_users.eml +++ b/src/ocamlorg_frontend/pages/industrial_users.eml @@ -53,7 +53,7 @@ let job_card (job: Data.Job.t) =
    -let render ~(users : Data.Industrial_user.t list) ~success_stories ~(top_story: Data.Success_story.t) ~(testimonials: Data.Testimonial.t list) ~jobs_with_count = +let render ~number_of_users ~(users : Data.Industrial_user.t list) ~success_stories ~(top_story: Data.Success_story.t) ~(testimonials: Data.Testimonial.t list) ~jobs_with_count = Layout.render ~use_swiper:true ~title:"OCaml in Industry" @@ -209,7 +209,7 @@ the community and learn more about how they use OCaml."
    diff --git a/src/ocamlorg_frontend/pages/is_ocaml_yet.eml b/src/ocamlorg_frontend/pages/is_ocaml_yet.eml index 57f2aa7060..1ba261882a 100644 --- a/src/ocamlorg_frontend/pages/is_ocaml_yet.eml +++ b/src/ocamlorg_frontend/pages/is_ocaml_yet.eml @@ -27,36 +27,11 @@ Learn_layout.three_column_layout <%s! meta.body_html %> - -
      -
    • - 🟢 : stable, tested and mature -
    • -
    • - 🟡 : getting there, stable but still maturing -
    • -
    • - 🟠 : not yet stable, but progressing -
    • -
    • - 🔴 : unstable/incomplete, needs work -
    • -
    • - 🆘 : barely there, needs serious work -
    • -

    Details

    <% meta.categories |> List.iter (fun (category : Data.Is_ocaml_yet.category) -> %>

    - <%s category.status %> <%s category.name %>

    <%s! category.description %>

    diff --git a/src/ocamlorg_frontend/pages/learn.eml b/src/ocamlorg_frontend/pages/learn.eml index 7802d1aec0..feec9c9966 100644 --- a/src/ocamlorg_frontend/pages/learn.eml +++ b/src/ocamlorg_frontend/pages/learn.eml @@ -70,8 +70,8 @@ Learn_layout.single_column_layout ] ~see_more:{href = Url.getting_started; title = "Get Started"} %> - <%s! Learn_components.tutorial_block ~icon:Learn_components.beginner_section_icon ~title:"LANGUAGE" ~heading:"The OCaml Language" - ~description:"An in-depth explanation of language features and data structures from the Standard Library" + <%s! Learn_components.tutorial_block ~icon:Learn_components.beginner_section_icon ~title:"LANGUAGE" ~heading:"The OCaml Language" + ~description:"An in-depth explanation of language features and data structures from the Standard Library" ~tutorial_links:[ {href = Url.tutorial "values-and-functions"; title = "Values and Functions"}; {href = Url.tutorial "basic-data-types"; title = "Data Types and Pattern Matching"}; @@ -129,8 +129,8 @@ Learn_layout.single_column_layout
    - <%s! Learn_components.tutorial_block ~icon:Learn_components.intermediate_section_icon ~title:"GUIDES" ~heading:"Practical-Minded Tutorials and Guides" - ~description:"How to solve real-world problems in OCaml" + <%s! Learn_components.tutorial_block ~icon:Learn_components.intermediate_section_icon ~title:"GUIDES" ~heading:"Practical-Minded Tutorials and Guides" + ~description:"How to solve real-world problems in OCaml" ~tutorial_links:[ {href = Url.tutorial "formatting-text"; title = "Formatting and Wrapping Text"}; {href = Url.tutorial "debugging"; title = "Debugging"}; @@ -139,13 +139,13 @@ Learn_layout.single_column_layout ] ~see_more:{href = Url.learn_guides; title = "See More Guides"} %> - <%s! Learn_components.tutorial_block ~icon:Learn_components.intermediate_section_icon ~title:"PLATFORM" ~heading:"The OCaml Platform" - ~description:"Learn to leverage the tooling around OCaml and create your own projects and libraries" + <%s! Learn_components.tutorial_block ~icon:Learn_components.intermediate_section_icon ~title:"PLATFORM" ~heading:"The OCaml Platform" + ~description:"Learn to leverage the tooling around OCaml and create your own projects and libraries" ~tutorial_links:[ {href = Url.tutorial "bootstrapping-a-dune-project"; title = "Bootstrapping a Project"}; {href = Url.tutorial "managing-dependencies"; title = "Managing Dependencies"}; {href = Url.tutorial "install-a-specific-ocaml-compiler-version"; title = "Install a Specific Compiler Version"}; - {href = Url.tutorial "configuring-your-editor"; title = "Configuring Your Editor"} + {href = Url.tutorial "set-up-editor"; title = "Configuring Your Editor"} ] ~see_more:{href = Url.learn_platform; title = "Platform Tools Documentation"} %> diff --git a/src/ocamlorg_frontend/pages/package_documentation.eml b/src/ocamlorg_frontend/pages/package_documentation.eml index 9632889a5b..9c2bd0f5d1 100644 --- a/src/ocamlorg_frontend/pages/package_documentation.eml +++ b/src/ocamlorg_frontend/pages/package_documentation.eml @@ -1,49 +1,48 @@ let sidebar ~str_path -~toc -~maptoc +~local_toc +~global_toc (package : Package.package) =
    - <% if (toc != []) then ( %> + <% if (local_toc != []) then ( %>
    - <%s! Toc.render toc %> + <%s! Toc.render local_toc %>
    <% ); %>
    - <%s! Navmap.render ~package ~path:str_path maptoc %> + <%s! Navmap.render ~package ~path:str_path global_toc %>
    let right_sidebar -~toc +~local_toc =
    - <%s! Toc.render toc %> + <%s! Toc.render local_toc %>
    let render ~(path: Package_breadcrumbs.path) ~page -~toc -~maptoc +~local_toc +~global_toc ~content (package : Package.package) = let str_path = match path with | Overview _ -> [] - | Documentation (docs_path) -> (match docs_path with - | Package_breadcrumbs.Index -> [] - | Library (s, p) -> s :: List.map (function - | Package_breadcrumbs.Module { name ; _ } -> name - | ModuleType { name ; _ } -> name - | Parameter { name ; _ } -> name - | Class { name ; _ } -> name - | ClassType { name ; _ } -> name - ) p - | Page s -> [""; s]) + | Documentation (docs_path) -> + List.map (function + | Package_breadcrumbs.Module { name ; _ } + | ModuleType { name ; _ } + | Parameter ({ name ; _ }, _) + | Class { name ; _ } + | ClassType { name ; _ } + | Page { name; _ } -> name + ) docs_path |> List.tl in Package_layout.render ~title:(Printf.sprintf "%s %s · OCaml Package" package.name (Package.render_version package)) @@ -54,10 +53,10 @@ Package_layout.render ~documentation_status:Success ~canonical:(Url.Package.documentation package.name ~version:(Package.specific_version package) ~page:(Url.Package.documentation ?version:(Some (Package.specific_version package)) package.name)) ~styles:["css/main.css"; "css/doc.css"] -~left_sidebar_html:(sidebar ~str_path ~toc ~maptoc package) -~right_sidebar_html:(right_sidebar ~toc) @@ +~left_sidebar_html:(sidebar ~str_path ~local_toc ~global_toc package) +~right_sidebar_html:(right_sidebar ~local_toc) @@
    - <%s! Package_breadcrumbs.render ~path package %> + <%s! Package_breadcrumbs.render ~path %>
    <%s! content %>
    diff --git a/src/ocamlorg_frontend/pages/package_overview.eml b/src/ocamlorg_frontend/pages/package_overview.eml index cdf8af70e2..67a86e2c02 100644 --- a/src/ocamlorg_frontend/pages/package_overview.eml +++ b/src/ocamlorg_frontend/pages/package_overview.eml @@ -68,10 +68,10 @@ in <%s! side_box_link ~icon_html:(Icons.package_homepage "h-4 w-4 mr-2 inline-block") ~href:homepage ~title:(Utils.host_of_uri homepage) %> <% ); %> <% (match sidebar_data.readme_filename with Some readme_filename -> %> - <%s! side_box_link ~icon_html:(Icons.changelog "h-4 w-4 mr-2 inline-block") ~href:(Url.Package.file package.name ?version ~filepath:(readme_filename ^ ".html")) ~title:"Readme" %> + <%s! side_box_link ~icon_html:(Icons.document "h-4 w-4 mr-2 inline-block") ~href:(Url.Package.file package.name ?version ~filepath:(readme_filename ^ ".html")) ~title:"Readme" %> <% | _ -> ()); %> <% (match sidebar_data.changes_filename with Some changes_filename -> %> - <%s! side_box_link ~icon_html:(Icons.changelog "h-4 w-4 mr-2 inline-block") ~href:(Url.Package.file package.name ?version ~filepath:(changes_filename ^ ".html")) ~title:"Changelog" %> + <%s! side_box_link ~icon_html:(Icons.document "h-4 w-4 mr-2 inline-block") ~href:(Url.Package.file package.name ?version ~filepath:(changes_filename ^ ".html")) ~title:"Changelog" %> <% | _ -> ()); %> <% (match sidebar_data.license_filename with Some license_filename -> %> <%s! side_box_link ~icon_html:(Icons.license "h-4 w-4 mr-2 inline-block") ~href:(Url.Package.file package.name ?version ~filepath:(license_filename ^ ".html")) ~title:( package.license ^ " License") %> diff --git a/src/ocamlorg_frontend/pages/tools_platform.eml b/src/ocamlorg_frontend/pages/tools_platform.eml index 010f4a6a1a..2a63a4ef9b 100644 --- a/src/ocamlorg_frontend/pages/tools_platform.eml +++ b/src/ocamlorg_frontend/pages/tools_platform.eml @@ -67,7 +67,7 @@ Tools_layout.three_column_layout href="<%s Url.installing_ocaml %>">"Installing OCaml".

    The Tools of the OCaml Platform

    - The individual OCaml Platform Tools go through a lifecycle from incubation to deprecation. + The individual OCaml Platform Tools go through a lifecycle from incubation to deprecation. Here is a list of all Platform Tools sorted by their lifecycle state.

    diff --git a/src/ocamlorg_frontend/pages/tutorial.eml b/src/ocamlorg_frontend/pages/tutorial.eml index 958d43b408..7584407573 100644 --- a/src/ocamlorg_frontend/pages/tutorial.eml +++ b/src/ocamlorg_frontend/pages/tutorial.eml @@ -18,7 +18,7 @@ let left_sidebar ~tutorials ~current_tutorial ~section = <%s! Learn_layout.render_sidebar ~tutorials ~current_tutorial ~section %>

    -let of_tutorial_section (s: Data.Tutorial.Section.t) = +let of_tutorial_section (s: Data.Tutorial.section) = match s with | GetStarted -> Learn_layout.GetStarted | Language -> Learn_layout.Language diff --git a/src/ocamlorg_package/lib/config.ml b/src/ocamlorg_package/lib/config.ml index 0896651660..dc7425a82d 100644 --- a/src/ocamlorg_package/lib/config.ml +++ b/src/ocamlorg_package/lib/config.ml @@ -5,7 +5,7 @@ let opam_polling = let documentation_url = Sys.getenv_opt "OCAMLORG_DOC_URL" - |> Option.value ~default:"https://docs-data.ocaml.org/live/" + |> Option.value ~default:"https://sage.ci.dev/current/" let package_caches_ttl = env_with_default "OCAMLORG_PACKAGE_CACHES_TTL" "3600" |> float_of_string diff --git a/src/ocamlorg_package/lib/documentation_status.ml b/src/ocamlorg_package/lib/documentation_status.ml index b9b4303bf4..754c67ab73 100644 --- a/src/ocamlorg_package/lib/documentation_status.ml +++ b/src/ocamlorg_package/lib/documentation_status.ml @@ -1,34 +1,27 @@ -type otherdocs = { - readme : string option; - license : string option; - changes : string option; -} +type redirection = { old_path : string; new_path : string } [@@deriving yojson] -type t = { failed : bool; otherdocs : otherdocs } +type t = { + name : string; + version : string; + failed : bool; + files : string list; + redirections : redirection list; +} +[@@deriving yojson] -let first_opt = function x :: _ -> Some x | [] -> None +let has_file (v : t) (options : string list) : string option = + let children = v.files in + try + List.find_map + (fun x -> + let fname = Fpath.(v x |> rem_ext |> filename) in + if List.mem fname options then Some fname else None) + children + with Not_found -> None -let strip_prefix (p : string option) = - let v : string list option = Option.map (String.split_on_char '/') p in - match v with - | None -> None - | Some (_ :: _ :: _ :: _ :: _ :: xs) -> Some (String.concat "/" xs) - | _ -> None +let license (v : t) = has_file v [ "LICENSE"; "LICENCE" ] +let readme (v : t) = has_file v [ "README"; "Readme"; "readme" ] -let of_yojson (v : Yojson.Safe.t) : t = - let status = Voodoo_serialize.Status.of_yojson v in - { - failed = status.failed; - otherdocs = - { - readme = - status.otherdocs.readme |> first_opt |> Option.map Fpath.to_string - |> strip_prefix; - license = - status.otherdocs.license |> first_opt |> Option.map Fpath.to_string - |> strip_prefix; - changes = - status.otherdocs.changes |> first_opt |> Option.map Fpath.to_string - |> strip_prefix; - }; - } +let changelog (v : t) = + has_file v + [ "CHANGELOG"; "Changelog"; "changelog"; "CHANGES"; "Changes"; "changes" ] diff --git a/src/ocamlorg_package/lib/documentation_status.mli b/src/ocamlorg_package/lib/documentation_status.mli index 90d1b0ad61..351558f577 100644 --- a/src/ocamlorg_package/lib/documentation_status.mli +++ b/src/ocamlorg_package/lib/documentation_status.mli @@ -2,13 +2,17 @@ ocaml-docs-ci. If the documentation generation is successful, this file should exist and contain info about the other pages present in the package. *) -type otherdocs = { - readme : string option; - license : string option; - changes : string option; -} +type redirection = { old_path : string; new_path : string } [@@deriving yojson] -type t = { failed : bool; otherdocs : otherdocs } +type t = { + name : string; + version : string; + failed : bool; + files : string list; + redirections : redirection list; +} +[@@deriving yojson] -val of_yojson : Yojson.Safe.t -> t -(** Parse the status from the JSON format of `status.json` *) +val readme : t -> string option +val license : t -> string option +val changelog : t -> string option diff --git a/src/ocamlorg_package/lib/dune b/src/ocamlorg_package/lib/dune index 141953c717..33299d609c 100644 --- a/src/ocamlorg_package/lib/dune +++ b/src/ocamlorg_package/lib/dune @@ -1,5 +1,6 @@ (library (name ocamlorg_package) + (preprocess (pps ppx_deriving_yojson)) (libraries opam-format bos diff --git a/src/ocamlorg_package/lib/ocamlorg_package.ml b/src/ocamlorg_package/lib/ocamlorg_package.ml index 086e485114..fc564d8c81 100644 --- a/src/ocamlorg_package/lib/ocamlorg_package.ml +++ b/src/ocamlorg_package/lib/ocamlorg_package.ml @@ -10,6 +10,7 @@ end module Version = OpamPackage.Version module Info = Info module Statistics = Packages_stats +module Sidebar = Sidebar type t = { name : Name.t; version : Version.t; info : Info.t } @@ -256,7 +257,11 @@ module Documentation = struct Parameter (int_of_string i) else raise (Invalid_argument ("kind not recognized: " ^ s)) - type breadcrumb = { name : string; href : string; kind : breadcrumb_kind } + type breadcrumb = { + name : string; + href : string option; + kind : breadcrumb_kind; + } type t = { uses_katex : bool; @@ -280,13 +285,17 @@ module Documentation = struct [ ("name", `String name); ("href", `String href); ("kind", `String kind); ] -> - { name; href; kind = breadcrumb_kind_from_string kind } + { name; href = Some href; kind = breadcrumb_kind_from_string kind } + | `Assoc [ ("name", `String name); ("href", `Null); ("kind", `String kind) ] + -> + { name; href = None; kind = breadcrumb_kind_from_string kind } | _ -> raise (Invalid_argument "malformed breadcrumb field") let doc_from_string s = match Yojson.Safe.from_string s with | `Assoc [ + ("header", `String header); ("type", `String _page_type); ("uses_katex", `Bool uses_katex); ("breadcrumbs", `List json_breadcrumbs); @@ -295,16 +304,12 @@ module Documentation = struct ("preamble", `String preamble); ("content", `String content); ] -> - let breadcrumbs = - match List.map breadcrumb_from_json json_breadcrumbs with - | _ :: _ :: _ :: _ :: breadcrumbs -> breadcrumbs - | _ -> failwith "Not enough breadcrumbs" - in + let breadcrumbs = List.map breadcrumb_from_json json_breadcrumbs in { uses_katex; breadcrumbs; toc = List.map toc_of_json json_toc; - content = preamble ^ content; + content = header ^ preamble ^ content; } | _ -> raise (Invalid_argument "malformed .html.json file") end @@ -345,20 +350,56 @@ let http_get url = Logs.err (fun m -> m "%s" (Printexc.to_string e)); Lwt.return (Error (`Msg (Printexc.to_string e)))) -let module_map ~kind t = +module Sidebar_cache : sig + val add : + Name.t -> + Version.t -> + [ `Package | `Universe of string ] -> + Sidebar.t -> + unit + + val get : + Name.t -> + Version.t -> + [ `Package | `Universe of string ] -> + Sidebar.t option +end = struct + let cache = Hashtbl.create 100 + + let add name version kind sidebar = + let name = Name.to_string name in + let version = Version.to_string version in + Hashtbl.add cache (name, version, kind) sidebar + + let get name version kind = + let name = Name.to_string name in + let version = Version.to_string version in + Hashtbl.find_opt cache (name, version, kind) +end + +let sidebar ~kind t = let package_url = package_url ~kind (Name.to_string t.name) (Version.to_string t.version) in let open Lwt.Syntax in - let url = package_url ^ "package.json" in - let+ content = http_get url in - match content with - | Ok v -> - let json = Yojson.Safe.from_string v in - Package_info.of_yojson json - | Error _ -> - Logs.info (fun m -> m "Failed to fetch module map at %s" url); - { Package_info.libraries = String.Map.empty } + match Sidebar_cache.get t.name t.version kind with + | Some sidebar -> Lwt.return sidebar + | None -> ( + let url = package_url ^ "doc/sidebar.json" in + let+ content = http_get url in + match content with + | Ok v -> ( + let json = Yojson.Safe.from_string v in + match Sidebar.of_yojson json with + | Ok x -> + Sidebar_cache.add t.name t.version kind x; + x + | Error msg -> + Logs.info (fun m -> m "Failed to parse sidebar at %s: %s" url msg); + []) + | Error _ -> + Logs.info (fun m -> m "Failed to fetch sidebar at %s" url); + []) let odoc_page ~url = let open Lwt.Syntax in @@ -395,7 +436,7 @@ let search_index ~kind t = let package_url = package_url ~kind (Name.to_string t.name) (Version.to_string t.version) in - let url = package_url ^ "index.js" in + let url = package_url ^ "doc/index.js" in let open Lwt.Syntax in let* content = http_get url in @@ -448,9 +489,13 @@ let documentation_status ~kind state t : Documentation_status.t option Lwt.t = let+ content = http_get (package_url ^ "status.json") in let status = match content with - | Ok s -> - Some (s |> Yojson.Safe.from_string |> Documentation_status.of_yojson) - | _ -> None + | Ok s -> ( + match + s |> Yojson.Safe.from_string |> Documentation_status.of_yojson + with + | Ok status -> Some status + | Error _TODO -> None) + | Error _TODO -> None in let status_entry = { documentation_status = status; time = Unix.gettimeofday () } diff --git a/src/ocamlorg_package/lib/ocamlorg_package.mli b/src/ocamlorg_package/lib/ocamlorg_package.mli index 70a3a34100..4665b766c1 100644 --- a/src/ocamlorg_package/lib/ocamlorg_package.mli +++ b/src/ocamlorg_package/lib/ocamlorg_package.mli @@ -81,7 +81,7 @@ module Documentation : sig | ClassType | File - type breadcrumb = { name : string; href : string; kind : breadcrumb_kind } + type breadcrumb = { name : string; href : string option; kind : breadcrumb_kind } type t = { uses_katex : bool; @@ -93,6 +93,8 @@ end module Package_info = Package_info +module Sidebar = Sidebar + type state type t @@ -111,15 +113,7 @@ val info : t -> Info.t val create : name:Name.t -> version:Version.t -> Info.t -> t (** This is added to enable demo test package to use Package.t with abstraction *) -module Documentation_status : sig - type otherdocs = { - readme : string option; - license : string option; - changes : string option; - } - - type t = { failed : bool; otherdocs : otherdocs } -end +module Documentation_status = Documentation_status val documentation_status : kind:[< `Package | `Universe of string ] -> @@ -128,9 +122,9 @@ val documentation_status : Documentation_status.t option Lwt.t (** Get the build status of the documentation of a package *) -val module_map : - kind:[< `Package | `Universe of string ] -> t -> Package_info.t Lwt.t -(** Get the module map of a package *) +val sidebar : + kind:[ `Package | `Universe of string ] -> t -> Sidebar.t Lwt.t +(** Get the sidebar of a package *) val documentation_page : kind:[< `Package | `Universe of string ] -> diff --git a/src/ocamlorg_package/lib/sidebar.ml b/src/ocamlorg_package/lib/sidebar.ml new file mode 100644 index 0000000000..dd133c4797 --- /dev/null +++ b/src/ocamlorg_package/lib/sidebar.ml @@ -0,0 +1,12 @@ +(** Odoc types for sidebar's global table of content *) + +type 'a node = { node : 'a; children : 'a node list } + +and sidebar_node = { + url : string option; + kind : string option; + content : string; +} + +and tree = sidebar_node node +and t = tree list [@@deriving of_yojson] diff --git a/src/ocamlorg_web/lib/config.ml b/src/ocamlorg_web/lib/config.ml index d8ba90020d..afd8cbe0b2 100644 --- a/src/ocamlorg_web/lib/config.ml +++ b/src/ocamlorg_web/lib/config.ml @@ -6,4 +6,6 @@ let to_bool s = let http_port = env_with_default "OCAMLORG_HTTP_PORT" "8080" |> int_of_string let manual_path = - env_with_default "OCAMLORG_MANUAL_PATH" "http-compiler-manuals" + env_with_default "OCAMLORG_MANUAL_PATH" "html-compiler-manuals" + +let v2_path = env_with_default "OCAMLORG_V2_PATH" "data/v2" diff --git a/src/ocamlorg_web/lib/handler.ml b/src/ocamlorg_web/lib/handler.ml index 180586268e..f98103579c 100644 --- a/src/ocamlorg_web/lib/handler.ml +++ b/src/ocamlorg_web/lib/handler.ml @@ -277,9 +277,13 @@ let learn_documents_search req = let changelog req = let current_tag = Dream.query req "t" in + let tags_from_change change = + match change with Data.Changelog.Release r -> r.tags | Post p -> p.tags + in let tags = Data.Changelog.all - |> List.concat_map (fun (change : Data.Changelog.t) -> change.tags) + |> List.concat_map (fun (change : Data.Changelog.t) -> + tags_from_change change) |> List.sort_uniq String.compare in let changes = @@ -288,7 +292,7 @@ let changelog req = | Some tag -> List.filter (fun (change : Data.Changelog.t) -> - List.exists (( = ) tag) change.tags) + List.exists (( = ) tag) (tags_from_change change)) Data.Changelog.all in @@ -328,6 +332,7 @@ let industrial_users _req = in let top_story = List.hd (sort_by_priority_desc Data.Success_story.all) in let users = Data.Industrial_user.featured |> Ocamlorg.Import.List.take 6 in + let number_of_users = List.length Data.Industrial_user.all in let success_stories = match sort_by_priority_desc Data.Success_story.all with | [] -> [] @@ -340,8 +345,8 @@ let industrial_users _req = let jobs_with_count = (jobs, List.length Data.Job.all) in Dream.html - (Ocamlorg_frontend.industrial_users ~users ~success_stories ~top_story - ~testimonials ~jobs_with_count) + (Ocamlorg_frontend.industrial_users ~number_of_users ~users ~success_stories + ~top_story ~testimonials ~jobs_with_count) let industrial_businesses _req = let businesses = Data.Industrial_user.all in @@ -886,29 +891,18 @@ module Package_helper = struct let package_sidebar_data ~kind t package = let open Lwt.Syntax in - let* package_documentation_status = - Ocamlorg_package.documentation_status ~kind t package - in + let* doc_status = Ocamlorg_package.documentation_status ~kind t package in let readme_filename = - Option.fold ~none:None - ~some:(fun (s : Ocamlorg_package.Documentation_status.t) -> - s.otherdocs.readme) - package_documentation_status + Option.bind doc_status Ocamlorg_package.Documentation_status.readme in let changes_filename = - Option.fold ~none:None - ~some:(fun (s : Ocamlorg_package.Documentation_status.t) -> - s.otherdocs.changes) - package_documentation_status + Option.bind doc_status Ocamlorg_package.Documentation_status.changelog in let license_filename = - Option.fold ~none:None - ~some:(fun (s : Ocamlorg_package.Documentation_status.t) -> - s.otherdocs.license) - package_documentation_status + Option.bind doc_status Ocamlorg_package.Documentation_status.license in let documentation_status = - match package_documentation_status with + match doc_status with | Some { failed = false; _ } -> Ocamlorg_frontend.Package.Success | Some { failed = true; _ } -> Failure | None -> Unknown @@ -1235,11 +1229,6 @@ let package_documentation t kind req = in let path = (Dream.path [@ocaml.warning "-3"]) req |> String.concat "/" in let hash = match kind with `Package -> None | `Universe u -> Some u in - let root = - Url.Package.documentation ?hash ~page:"" - ?version:(Ocamlorg_frontend.Package.url_version frontend_package) - (Ocamlorg_package.Name.to_string name) - in let* docs = Ocamlorg_package.documentation_page ~kind package path in match docs with | None -> @@ -1247,7 +1236,7 @@ let package_documentation t kind req = Dream.html ~code:404 (Ocamlorg_frontend.package_documentation_not_found ~page:path ~search_index_digest:None - ~path:(Ocamlorg_frontend.Package_breadcrumbs.Documentation Index) + ~path:(Ocamlorg_frontend.Package_breadcrumbs.Documentation []) frontend_package) in if version_from_url = "latest" then @@ -1264,95 +1253,63 @@ let package_documentation t kind req = (Ocamlorg_package.Name.to_string name)) else response_404_page | Some doc -> - let module Package_info = Ocamlorg_package.Package_info in - let rec toc_of_module ~root - (module' : Ocamlorg_package.Package_info.Module.t) : - Ocamlorg_frontend.Navmap.toc = - let title = Package_info.Module.name module' in - let kind = Package_info.Module.kind module' in - let href = Some (root ^ Package_info.Module.path module') in - let children = - module' |> Package_info.Module.submodules |> String.Map.bindings - |> List.map (fun (_, module') -> toc_of_module ~root module') - in - let kind = - match (kind : Package_info.Kind.t) with - | Page -> Ocamlorg_frontend.Navmap.Page - | Module -> Module - | LeafPage -> Leaf_page - | ModuleType -> Module_type - | Parameter _ -> Parameter - | Class -> Class - | ClassType -> Class_type - | File -> File - in - Ocamlorg_frontend.Navmap.{ title; href; kind; children } + let map_url = Option.map (fun url -> "/" ^ url) in + let rec navmap_of_sidebar (sidebar : Ocamlorg_package.Sidebar.tree) = + Ocamlorg_frontend.Navmap. + { + title = sidebar.node.content; + kind = + (match sidebar.node.kind with + | Some "module" -> Module + | (Some ("page" | "leaf-page") | None) + when String.starts_with ~prefix:"Library " sidebar.node.content + -> + Library + | Some ("page" | "leaf-page") -> Page + | Some "module-type" -> Module_type + | Some "parameter" -> Parameter + | Some "class" -> Class + | Some "class-type" -> Class_type + | Some "file" -> File + | None -> Page + | _ -> File); + href = map_url sidebar.node.url; + children = List.map navmap_of_sidebar sidebar.children; + } in - let toc_of_map ~root (map : Ocamlorg_package.Package_info.t) : - Ocamlorg_frontend.Navmap.t = - let libraries = map.libraries in - String.Map.bindings libraries - |> List.map (fun (_, (library : Package_info.library)) -> - let title = library.name in - let href = None in - let children = - String.Map.bindings library.modules - |> List.map (fun (_, module') -> toc_of_module ~root module') - in - Ocamlorg_frontend.Navmap. - { title; href; kind = Library; children }) - in - let* module_map = Ocamlorg_package.module_map ~kind package in + let* sidebar = Ocamlorg_package.sidebar ~kind package in let* search_index_digest = Package_helper.search_index_digest ~kind t package in - let toc = Package_helper.frontend_toc doc.toc in - let (maptoc : Ocamlorg_frontend.Navmap.toc list) = - toc_of_map ~root module_map + let local_toc = Package_helper.frontend_toc doc.toc in + let (global_toc : Ocamlorg_frontend.Navmap.toc list) = + List.map navmap_of_sidebar sidebar in let (breadcrumb_path : Ocamlorg_frontend.Package_breadcrumbs.path) = let breadcrumbs = doc.breadcrumbs in - if breadcrumbs != [] then - let first_path_item = List.hd breadcrumbs in - let doc_breadcrumb_to_library_path_item - (p : Ocamlorg_package.Documentation.breadcrumb) = - match p.kind with - | Module -> - Ocamlorg_frontend.Package_breadcrumbs.Module - { name = p.name; href = p.href } - | ModuleType -> ModuleType { name = p.name; href = p.href } - | Parameter i -> - Parameter { name = p.name; href = p.href; number = i } - | Class -> Class { name = p.name; href = p.href } - | ClassType -> ClassType { name = p.name; href = p.href } - | Page | LeafPage | File -> - failwith "library paths do not contain Page, LeafPage or File" + let doc_breadcrumb_to_library_path_item + (p : Ocamlorg_package.Documentation.breadcrumb) = + let b = + { + Ocamlorg_frontend.Package_breadcrumbs.name = p.name; + href = p.href; + } in + match p.kind with + | Module -> Ocamlorg_frontend.Package_breadcrumbs.Module b + | ModuleType -> ModuleType b + | Parameter i -> Parameter (b, i) + | Class -> Class b + | ClassType -> ClassType b + | Page | LeafPage | File -> Page b + in - match first_path_item.kind with - | Page | LeafPage | File -> - Ocamlorg_frontend.Package_breadcrumbs.Documentation - (Page first_path_item.name) - | Module | ModuleType | Parameter _ | Class | ClassType -> - let library = - List.find_opt - (fun (toc : Ocamlorg_frontend.Navmap.toc) -> - List.exists - (fun (t : Ocamlorg_frontend.Navmap.toc) -> - t.title = first_path_item.name) - toc.children) - maptoc - in - - Ocamlorg_frontend.Package_breadcrumbs.Documentation - (Library - ( (match library with Some l -> l.title | None -> "unknown"), - List.map doc_breadcrumb_to_library_path_item breadcrumbs )) - else Ocamlorg_frontend.Package_breadcrumbs.Documentation Index + Ocamlorg_frontend.Package_breadcrumbs.Documentation + (List.map doc_breadcrumb_to_library_path_item breadcrumbs) in Dream.html (Ocamlorg_frontend.package_documentation ~page:(Some path) - ~search_index_digest ~path:breadcrumb_path ~toc ~maptoc + ~search_index_digest ~path:breadcrumb_path ~local_toc ~global_toc ~content:doc.content frontend_package) let package_file t kind req = @@ -1414,3 +1371,10 @@ let sitemap _request = Dream.flush stream) let logos _req = Dream.html (Ocamlorg_frontend.logos ()) + +let v2_asset req = + let? path = + try Some (Config.v2_path ^ Dream.target req) with _ -> None + in + let? () = if Sys.file_exists path then Some () else None in + Filename.(Dream.from_filesystem (dirname path) (basename path) req) diff --git a/src/ocamlorg_web/lib/redirection.ml b/src/ocamlorg_web/lib/redirection.ml index e24294c4de..3e454be805 100644 --- a/src/ocamlorg_web/lib/redirection.ml +++ b/src/ocamlorg_web/lib/redirection.ml @@ -1,43 +1,28 @@ open Ocamlorg -let fwd_v2 target = (target, Url.v2 ^ target) - -(* For assets previously hosted on V2, we redirect the requests to - v2.ocaml.org. *) let v2_assets = - [ - "/meetings/ocaml/2013/proposals/core-bench.pdf"; - "/meetings/ocaml/2013/proposals/ctypes.pdf"; - "/meetings/ocaml/2013/proposals/formats-as-gadts.pdf"; - "/meetings/ocaml/2013/proposals/frenetic.pdf"; - "/meetings/ocaml/2013/proposals/goji.pdf"; - "/meetings/ocaml/2013/proposals/gpgpu.pdf"; - "/meetings/ocaml/2013/proposals/injectivity.pdf"; - "/meetings/ocaml/2013/proposals/merlin.pdf"; - "/meetings/ocaml/2013/proposals/ocamlot.pdf"; - "/meetings/ocaml/2013/proposals/optimizations.pdf"; - "/meetings/ocaml/2013/proposals/platform.pdf"; - "/meetings/ocaml/2013/proposals/profiling-memory.pdf"; - "/meetings/ocaml/2013/proposals/runtime-types.pdf"; - "/meetings/ocaml/2013/proposals/weather-related-data.pdf"; - "/meetings/ocaml/2013/proposals/wxocaml.pdf"; - "/meetings/ocaml/2013/slides/bourgoin.pdf"; - "/meetings/ocaml/2013/slides/bozman.pdf"; - "/meetings/ocaml/2013/slides/canou.pdf"; - "/meetings/ocaml/2013/slides/carty.pdf"; - "/meetings/ocaml/2013/slides/chambart.pdf"; - "/meetings/ocaml/2013/slides/garrigue.pdf"; - "/meetings/ocaml/2013/slides/guha.pdf"; - "/meetings/ocaml/2013/slides/henry.pdf"; - "/meetings/ocaml/2013/slides/james.pdf"; - "/meetings/ocaml/2013/slides/lefessant.pdf"; - "/meetings/ocaml/2013/slides/leroy.pdf"; - "/meetings/ocaml/2013/slides/madhavapeddy.pdf"; - "/meetings/ocaml/2013/slides/padioleau.pdf"; - "/meetings/ocaml/2013/slides/sheets.pdf"; - "/meetings/ocaml/2013/slides/vaugon.pdf"; - "/meetings/ocaml/2013/slides/white.pdf"; - ] + let confs = + [ "/conference/"; "/meetings/"; "/meeting/"; "/workshops/"; "/workshop/" ] + in + let redirects confs target source = + let f s = (s ^ source, target) in + List.map f confs + in + let f path = + let open String in + if starts_with ~prefix:"/conferences/" path && ends_with ~suffix:".pdf" path + then redirects confs path (sub path 13 (length path - 13)) + else [] + in + let g conf = + let year = String.sub conf.Data.Conference.date 0 4 in + [ ""; "/index.html" ] + |> List.concat_map (fun s -> + redirects ("/conferences/" :: confs) + ("/conferences/" ^ conf.slug) + ("ocaml/" ^ year ^ s)) + in + List.concat_map f Data.V2.assets @ List.concat_map g Data.Conference.all let from_v2 = [ @@ -228,91 +213,30 @@ let from_v2 = ("/learn/tutorials/streams.html", Url.tutorial "sequences"); ("/learn/tutorials/up_and_running.html", Url.tutorial "up-and-running"); (Url.tutorial "first-hour", Url.tutorial "tour-of-ocaml"); - ("/meetings/index.fr.html", Url.community); - ("/meetings/index.html", Url.community); - ("/meetings", Url.community); - ( "/meetings/ocaml/2008/index.html", - Url.conference "ocaml-users-and-developers-conference-2008" ); - ( "/meetings/ocaml/2008", - Url.conference "ocaml-users-and-developers-conference-2008" ); - ( "/meetings/ocaml/2008/index.html", - Url.conference "ocaml-users-and-developers-conference-2008" ); - ( "/meetings/ocaml/2008", - Url.conference "ocaml-users-and-developers-conference-2008" ); - ( "/meetings/ocaml/2009/index.html", - Url.conference "ocaml-users-and-developers-conference-2009" ); - ( "/meetings/ocaml/2009", - Url.conference "ocaml-users-and-developers-conference-2009" ); - ( "/meetings/ocaml/2010/index.html", - Url.conference "ocaml-users-and-developers-conference-2010" ); - ( "/meetings/ocaml/2010", - Url.conference "ocaml-users-and-developers-conference-2010" ); - ( "/meetings/ocaml/2011/index.html", - Url.conference "ocaml-users-and-developers-conference-2011" ); - ( "/meetings/ocaml/2011", - Url.conference "ocaml-users-and-developers-conference-2011" ); - ( "/meetings/ocaml/2012/index.html", - Url.conference "ocaml-users-and-developers-conference-2012" ); + ("/meetings/index.fr.html", Url.conferences); + ("/meetings/index.html", Url.conferences); + ("/meetings", Url.conferences); ( "/meetings/ocaml/2013/call.html", Url.conference "ocaml-users-and-developers-conference-2013" ); - ( "/meetings/ocaml/2013", - Url.conference "ocaml-users-and-developers-conference-2013" ); - ( "/meetings/ocaml/2013/index.html", - Url.conference "ocaml-users-and-developers-conference-2013" ); ( "/meetings/ocaml/2013/program.html", Url.conference "ocaml-users-and-developers-conference-2013" ); - ( "/meetings/ocaml/2013", - Url.conference "ocaml-users-and-developers-conference-2013" ); ( "/meetings/ocaml/2013/talks/index.html", Url.conference "ocaml-users-and-developers-conference-2013" ); ( "/meetings/ocaml/2014/cfp.html", Url.conference "ocaml-users-and-developers-conference-2014" ); - ( "/meetings/ocaml/2014", - Url.conference "ocaml-users-and-developers-conference-2014" ); - ( "/meetings/ocaml/2014/index.html", - Url.conference "ocaml-users-and-developers-conference-2014" ); ( "/meetings/ocaml/2014/ocaml2014_10.html", Url.conference "ocaml-users-and-developers-conference-2014" ); ( "/meetings/ocaml/2014/program.html", Url.conference "ocaml-users-and-developers-conference-2014" ); ( "/meetings/ocaml/2015/cfp.html", Url.conference "ocaml-users-and-developers-conference-2015" ); - ( "/meetings/ocaml/2015", - Url.conference "ocaml-users-and-developers-conference-2015" ); - ( "/meetings/ocaml/2015/index.html", - Url.conference "ocaml-users-and-developers-conference-2015" ); - ( "/meetings/ocaml/2015", - Url.conference "ocaml-users-and-developers-conference-2015" ); ( "/meetings/ocaml/2015/program.html", Url.conference "ocaml-users-and-developers-conference-2015" ); - ( "/meetings/ocaml/2015", - Url.conference "ocaml-users-and-developers-conference-2015" ); ( "/meetings/ocaml/2015/program.txt", Url.conference "ocaml-users-and-developers-conference-2015" ); - ( "/meetings/ocaml/2015", - Url.conference "ocaml-users-and-developers-conference-2015" ); - ( "/meetings/ocaml/2016/index.html", - Url.conference "ocaml-users-and-developers-conference-2016" ); - ( "/meetings/ocaml/2016", - Url.conference "ocaml-users-and-developers-conference-2016" ); - ( "/meetings/ocaml/2017/index.html", - Url.conference "ocaml-users-and-developers-conference-2017" ); - ( "/meetings/ocaml/2017", - Url.conference "ocaml-users-and-developers-conference-2017" ); - ( "/meetings/ocaml/2018/index.html", - Url.conference "ocaml-users-and-developers-conference-2018" ); - ( "/meetings/ocaml/2018", - Url.conference "ocaml-users-and-developers-conference-2018" ); - ( "/meetings/ocaml/2019/index.html", - Url.conference "ocaml-users-and-developers-conference-2019" ); - ( "/meetings/ocaml/2019", - Url.conference "ocaml-users-and-developers-conference-2019" ); - ( "/meetings/ocaml/2020/index.html", - Url.conference "ocaml-users-and-developers-conference-2020" ); - ( "/meetings/ocaml/2020", - Url.conference "ocaml-users-and-developers-conference-2020" ); - ("/meetings/ocaml/index.html", Url.community); - ("/meetings/ocaml", Url.community); + ("/meetings/ocaml/index.html", Url.conferences); + ("/meetings/ocaml", Url.conferences); + ("/workshops", Url.conferences); ("/ocamllabs/index.html", Url.index); ("/ocamllabs", Url.index); ("/platform/index.html", Url.learn_platform); @@ -327,6 +251,7 @@ let from_v2 = ("/docs/platform-principles", Url.tool_page "platform-principles"); ("/docs/platform-users", Url.tool_page "platform-users"); ("/docs/platform-roadmap", Url.tool_page "platform-roadmap"); + ("/docs/configuring-your-editor", Url.tutorial "set-up-editor"); ] let make ?(permanent = false) t = @@ -340,30 +265,6 @@ let make ?(permanent = false) t = Some (Dream.get origin (fun req -> Dream.redirect ~status req new_))) t) -let ocaml_workshops = - List.map - (fun (slug : string) -> - make ~permanent:true [ ("/workshop/" ^ slug, Url.conference slug) ]) - [ - "ocaml-users-and-developers-conference-2008"; - "ocaml-users-and-developers-conference-2009"; - "ocaml-users-and-developers-conference-2010"; - "ocaml-users-and-developers-conference-2011"; - "ocaml-users-and-developers-conference-2012"; - "ocaml-users-and-developers-conference-2013"; - "ocaml-users-and-developers-conference-2014"; - "ocaml-users-and-developers-conference-2015"; - "ocaml-users-and-developers-conference-2016"; - "ocaml-users-and-developers-conference-2017"; - "ocaml-users-and-developers-conference-2018"; - "ocaml-users-and-developers-conference-2019"; - "ocaml-users-and-developers-conference-2020"; - "ocaml-users-and-developers-conference-2020"; - "ocaml-users-and-developers-conference-2021"; - "ocaml-users-and-developers-conference-2022"; - "ocaml-users-and-developers-conference-2023"; - ] - let package req = let package = Dream.param req "name" in Dream.redirect req (Url.Package.overview package) @@ -374,22 +275,19 @@ let package_docs req = let t = Dream.scope "" [] - ([ - make ~permanent:true [ ("feed.xml", "planet.xml") ]; - make from_v2; - make (List.map fwd_v2 v2_assets); - make [ ("/blog", "/ocaml-planet") ]; - make ~permanent:true [ ("/opportunities", "/jobs") ]; - make ~permanent:true - [ ("/carbon-footprint", "/policies/carbon-footprint") ]; - make ~permanent:true [ ("/privacy-policy", "/policies/privacy-policy") ]; - make ~permanent:true - [ ("/code-of-conduct", "/policies/code-of-conduct") ]; - make ~permanent:true [ ("/opportunities", "/jobs") ]; - (* make ~permanent:false [ (Url.conferences, Url.community ^ - "#conferences") ]; *) - Dream.get "/p/:name" package; - Dream.get "/u/:hash/p/:name" package; - Dream.get "/p/:name/doc" package_docs; - ] - @ ocaml_workshops) + [ + make ~permanent:true [ ("feed.xml", "planet.xml") ]; + make ~permanent:true from_v2; + make ~permanent:true v2_assets; + make ~permanent:true [ ("/blog", "/ocaml-planet") ]; + make ~permanent:true [ ("/opportunities", "/jobs") ]; + make ~permanent:true + [ ("/carbon-footprint", "/policies/carbon-footprint") ]; + make ~permanent:true [ ("/privacy-policy", "/policies/privacy-policy") ]; + make ~permanent:true [ ("/code-of-conduct", "/policies/code-of-conduct") ]; + (* make ~permanent:false [ (Url.conferences, Url.community ^ + "#conferences") ]; *) + Dream.get "/p/:name" package; + Dream.get "/u/:hash/p/:name" package; + Dream.get "/p/:name/doc" package_docs; + ] diff --git a/src/ocamlorg_web/lib/router.ml b/src/ocamlorg_web/lib/router.ml index d144c42ebb..80dd71a8ec 100644 --- a/src/ocamlorg_web/lib/router.ml +++ b/src/ocamlorg_web/lib/router.ml @@ -127,16 +127,32 @@ let graphql_route t = Dream.get "/graphiql" (Dream.graphiql "/graphql"); ] +let ( let+ ) x f = Lwt.map f x + +let middleware_text_utf8 handler request = + let+ response = handler request in + let ( let& ) opt some = Option.fold ~none:response ~some opt in + let headers = Dream.all_headers response in + let& content_type = List.assoc_opt "Content-Type" headers in + let& _ = + if String.starts_with ~prefix:"text/plain" content_type then Some () + else None + in + Dream.drop_header response "Content-Type"; + Dream.add_header response "Content-Type" (content_type ^ "; charset=utf-8"); + response + let router t = Dream.router [ Redirection.t; + Dream.get "/conferences/ocaml/**" Handler.v2_asset; page_routes t; package_route t; graphql_route t; sitemap_routes; Dream.scope "" - [ Dream_encoding.compress ] + [ Dream_encoding.compress; middleware_text_utf8 ] [ Dream.get "/manual/**" (Dream.static Config.manual_path) ]; Dream.scope "" [ Dream_encoding.compress ] diff --git a/src/ocamlorg_web/lib/sitemap.ml b/src/ocamlorg_web/lib/sitemap.ml index e91489ad45..1a81ab32ff 100644 --- a/src/ocamlorg_web/lib/sitemap.ml +++ b/src/ocamlorg_web/lib/sitemap.ml @@ -43,7 +43,12 @@ let urlables = List.to_seq [ Urlable (urls, to_url); - Urlable (Changelog.all, fun r -> to_url @@ Url.changelog_entry r.slug); + Urlable + ( Changelog.all, + fun r -> + match r with + | Release r -> to_url @@ Url.changelog_entry r.slug + | Post r -> to_url @@ Url.changelog_entry r.slug ); Urlable (Governance.teams, fun r -> to_url @@ Url.governance_team r.id); Urlable (Is_ocaml_yet.all, fun r -> to_url @@ Url.is_ocaml_yet r.id); Urlable (News.all, fun r -> to_url @@ Url.news_post r.slug); diff --git a/test/load-test/k6/.gitignore b/test/load-test/k6/.gitignore new file mode 100644 index 0000000000..df9d16b899 --- /dev/null +++ b/test/load-test/k6/.gitignore @@ -0,0 +1 @@ +_results/ diff --git a/test/load-test/k6/README.md b/test/load-test/k6/README.md new file mode 100644 index 0000000000..e9bcbfe493 --- /dev/null +++ b/test/load-test/k6/README.md @@ -0,0 +1,45 @@ +# k6 Load Tests + +This directory contains a [k6](https://grafana.com/docs/k6/latest/) script for +load testing ocaml.org endpoints. + +- The k6 test script is defined in [./script.js](./script.js). +- The runner script [./run.sh](./run.sh) will run `./script.js` with the k6 + docker image. + + +## Running load tests + +### Prerequisites + +- docker +- k6parser +- xdg-open (MacOS users may need to adjust the runner script) + +### Usage + +``` sh +./run.sh script.js +``` + +will run a load test against all defined endpoints using 10 virtual users, and +running for 30 seconds. + +You can specify different values for the concurrent users and duration using the +`--vus` and `--duration` flags, respectively. E.g., to test with 100 virtual +users for one minute: + +``` sh +./run.sh --vus 100 --duration 1m script.js +``` + +## Reviewing the results + +k6 will print out the a summary of results when the test is finished. See + for +documentation on how to interpret the results. + +- Detailed results are written to a gzipped JOSN file + `_results/{day}T{time}-results.gz`. +- A browser will be opened with a visualization plotting general responsiveness, + loaded with the file `_results/{day}T{time}-results.report`. diff --git a/test/load-test/k6/run.sh b/test/load-test/k6/run.sh new file mode 100755 index 0000000000..12ef3cd4bc --- /dev/null +++ b/test/load-test/k6/run.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env sh + +# Ignore posix compliance errors in shellcheck +#shellcheck disable=SC3000-SC3061 + +set -eu +set -o pipefail + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +RESULTS_DIR=_results +USER_ID=$(id -u) # ensure we can write to the mounted dir +TIME=$(date +%FT%T) +RESULTS="${RESULTS_DIR}/${TIME}-results.gz" +GRAPH="${RESULTS_DIR}/${TIME}-report.html" + + +mkdir -p "$RESULTS_DIR" + +docker run --rm \ + -u "$USER_ID" \ + -v "$SCRIPT_DIR":/home/k6 grafana/k6 \ + --out json="$RESULTS" \ + "$@" + +k6parser "$RESULTS" --output "$GRAPH" + +xdg-open "$GRAPH" diff --git a/test/load-test/k6/script.js b/test/load-test/k6/script.js new file mode 100644 index 0000000000..3bc97945f5 --- /dev/null +++ b/test/load-test/k6/script.js @@ -0,0 +1,88 @@ +import http from "k6/http"; +import { sleep } from "k6"; + +export const options = { + // A number specifying the number of VUs to run concurrently. + vus: 10, + // A string specifying the total duration of the test run. + duration: "30s", + + // The following section contains configuration options for execution of this + // test script in Grafana Cloud. + // + // See https://grafana.com/docs/grafana-cloud/k6/get-started/run-cloud-tests-from-the-cli/ + // to learn about authoring and running k6 test scripts in Grafana k6 Cloud. + // + // cloud: { + // // The ID of the project to which the test is assigned in the k6 Cloud UI. + // // By default tests are executed in default project. + // projectID: "", + // // The name of the test in the k6 Cloud UI. + // // Test runs with the same name will be grouped. + // name: "script.js" + // }, + + // Uncomment this section to enable the use of Browser API in your tests. + // + // See https://grafana.com/docs/k6/latest/using-k6-browser/running-browser-tests/ to learn more + // about using Browser API in your test scripts. + // + // scenarios: { + // // The scenario name appears in the result summary, tags, and so on. + // // You can give the scenario any name, as long as each name in the script is unique. + // ui: { + // // Executor is a mandatory parameter for browser-based tests. + // // Shared iterations in this case tells k6 to reuse VUs to execute iterations. + // // + // // See https://grafana.com/docs/k6/latest/using-k6/scenarios/executors/ for other executor types. + // executor: 'shared-iterations', + // options: { + // browser: { + // // This is a mandatory parameter that instructs k6 to launch and + // // connect to a chromium-based browser, and use it to run UI-based + // // tests. + // type: 'chromium', + // }, + // }, + // }, + // } +}; + +// The function that defines VU logic. +// +// See https://grafana.com/docs/k6/latest/examples/get-started-with-k6/ to learn more +// about authoring k6 scripts. + +const base_url = "http://localhost:8080"; + +function endpoint(u) { + return base_url + u; +} + +export default function () { + // Landing page + http.get(endpoint("/")); + + // Core doc page + http.get(endpoint("/p/core/latest/doc/index.html")); + + // Top level pages + http.get(endpoint("/install")); + http.get(endpoint("/docs/tour-of-ocaml")); + http.get(endpoint("/docs")); + http.get(endpoint("/platform")); + http.get(endpoint("/packages")); + http.get(endpoint("/community")); + http.get(endpoint("/changelog")); + http.get(endpoint("/play")); + http.get(endpoint("/industrial-users")); + http.get(endpoint("/academic-users")); + + // some package searches + // Grouping the urls, see https://grafana.com/docs/k6/latest/using-k6/http-requests/#url-grouping + const package_search_tag = { tags: { name: "PacakageSearch" } }; + ["http", "server", "cli", "core", "eio", "graph"].forEach((q) => { + http.get(endpoint(`/packages/autocomplete?q=${q}`), package_search_tag); + http.get(endpoint(`/packages/search?q=${q}`), package_search_tag); + }); +} diff --git a/test/load-test/locust/.gitignore b/test/load-test/locust/.gitignore new file mode 100644 index 0000000000..c18dd8d83c --- /dev/null +++ b/test/load-test/locust/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/test/load-test/locust/README.md b/test/load-test/locust/README.md new file mode 100644 index 0000000000..6dc71d2580 --- /dev/null +++ b/test/load-test/locust/README.md @@ -0,0 +1,40 @@ +# Locust Load Tests + +This directory contains a [locust](https://locust.io/) script for load testing +ocaml.org endpoints. + +## Running simple load tests + +1. Start the test framework running with + + ``` sh + ./main.sh + ``` + +2. Navigate to http://0.0.0.0:8089 + +3. Configure + - the max number of users to simulate + - the number of new users to add to the simulation every second + - the host (e.g., `http://localhost:8080`) + +## Running load tests with multiple cores + +``` sh +./main.sh n +``` + +where `n` is the number of processes to run concurrently. + +## Reviewing the load tests + +- Click "Stop" when you are finished running your test. +- Review the various tabs, or click "Download data" for options to download the + test results. +- You can also review prometheus metrics about the staging and prod servers at + https://status.ocaml.ci.dev/d/be358r0z9ai9sf/ocaml-org + +## Adding new routines + +Tests are defined as "tasks" (sequences of site traversal) in +[./locustfile.py](./locustfile.py). diff --git a/test/load-test/locust/locustfile.py b/test/load-test/locust/locustfile.py new file mode 100644 index 0000000000..7829c68508 --- /dev/null +++ b/test/load-test/locust/locustfile.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# +import random +from locust import FastHttpUser, task, between + +# obtained via https://random-word-api.herokuapp.com/word?number=200 +words = ["sacraria","seedcake","philtered","leadiest","cloverleafs","snaffle","lyrisms","ankhs","bedtimes","carrier","restabling","playlets","occupation","overreport","printers","scintigraphic","spa","corsages","enwound","gossipmonger","hydragog","waterlily","avulsions","sonneteerings","spilt","hemocytes","tamandus","rais","minaret","coliseums","ultramicrotome","attribute","phosphite","scincoids","scooting","frightfulnesses","carbamides","sculpture","irresponsive","overtasks","expertise","weet","consociations","tulles","hared","pigginesses","oversimple","theologs","adverb","inamoratas","teeny","rapacities","assonant","metestrus","cyanohydrin","smiting","polychete","merest","tautological","phyllopod","petahertz","plainspokenness","pavior","penitently","omikrons","cigarlike","foetal","diebacks","downlight","kinship","warmish","titleholders","suppositions","resuscitations","tiffing","outsung","homed","alternated","cranks","piaster","allotters","nonirradiated","protohistories","finned","decouple","shahs","foeman","perfidious","soarers","thoroughpins","gastrulating","thrivers","convention","roughened","uncircumcised","clabbering","leadscrew","panfuls","nilgais","evolver","overvoting","furrower","ichthyosaurs","internalizes","borschts","regrouping","lordlier","roguish","microseismicity","besmiling","mattoids","cholerically","fibrosarcomas","farinha","curricles","triradiate","beringed","electrolysis","kashmirs","dirdums","ignorami","otalgic","lusciously","blotty","pizzaz","educe","pendant","disposable","autolyzes","outjutting","interfused","operagoers","fustian","theretofore","dean","unsullied","goitrogenic","ultrasafe","potboil","geochemistries","outdesigned","ephedras","woodlore","illuminatingly","guardrooms","sheldrakes","leachable","theistically","reconception","beachboys","recriminates","almuds","changeabilities","flareups","machinate","verbalizations","dendrologist","unkept","copulatives","restyles","parceled","caecilians","mortgager","thunderstones","labarums","wiliness","hydroplane","already","unlatch","swineherds","alternate","whodunit","hoodiest","sainted","detract","inspiring","fantastically","macaws","adsorbs","thickets","blogs","greenfields","ariettes","camphor","hornpipe","uninventive","boatyard","boomiest","lollingly","congresspersons","painter","radiocarbons","impiously","unfeigned","matchlocks","screwballs","stickies","muddlers","resentful","meats"] + +class OcamlOrgUsere(FastHttpUser): + wait_time = between(1, 5) # range of seconds a user waits between clicks + + @task + def landing(self): + self.client.get("/") + self.client.get("/install") + self.client.get("/p/core/latest/doc/index.html") + self.client.get("/docs/tour-of-ocaml") + + @task + def top_level_pages(self): + self.client.get("/docs") + self.client.get("/platform") + self.client.get("/packages") + self.client.get("/community") + self.client.get("/changelog") + self.client.get("/play") + self.client.get("/industrial-users") + self.client.get("/academic-users") + + @task + def package_searches(self): + query = random.choice(words) + self.client.get(f"/packages/autocomplete?q={query}") + self.client.get(f"/packages/search?q={query}") diff --git a/test/load-test/locust/main.sh b/test/load-test/locust/main.sh new file mode 100755 index 0000000000..4ea0b3dd4c --- /dev/null +++ b/test/load-test/locust/main.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env sh + +# Ignore posix compliance errors in shellcheck +#shellcheck disable=SC3000-SC3061 + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +# see https://docs.locust.io/en/stable/running-distributed.html#distributed-load-generation +n_procs="$1" + +docker run -p 8089:8089 -v "$SCRIPT_DIR":/mnt/locust locustio/locust \ + --locustfile /mnt/locust/locustfile.py \ + ${n_procs:+"--processes=${n_procs}"} # Build the --processes flag if n_procs is not nil diff --git a/tool/ood-gen/lib/academic_institution.ml b/tool/ood-gen/lib/academic_institution.ml index 7bdfdfee9b..5eeae369cd 100644 --- a/tool/ood-gen/lib/academic_institution.ml +++ b/tool/ood-gen/lib/academic_institution.ml @@ -1,5 +1,3 @@ -open Data_intf.Academic_institution - type course_metadata = { name : string; acronym : string option; @@ -15,6 +13,18 @@ type course_metadata = { } [@@deriving of_yaml] +module Ptime = struct + include Ptime + + let pp fmt t = + Format.pp_print_string fmt "(Ptime.of_rfc3339 \""; + Ptime.pp_rfc3339 () fmt t; + Format.pp_print_string fmt + "\" |> function Ok (t, _, _) -> t | Error _ -> failwith \"RFC 3339\")" +end + +type course = [%import: Data_intf.Academic_institution.course] [@@deriving show] + let course_metadata_to_course ~modify_last_check (c : course_metadata) : course = Data_intf.Academic_institution. @@ -47,6 +57,9 @@ let course_of_yaml yaml = Ok (course_metadata_to_course ~modify_last_check metadata) with Failure msg -> Error (`Msg msg) +type location = [%import: Data_intf.Academic_institution.location] +[@@deriving of_yaml, show] + type metadata = { name : string; description : string; @@ -59,9 +72,15 @@ type metadata = { image : string option; alternate_logo : string option; } -[@@deriving of_yaml, stable_record ~version:t ~add:[ body_md; body_html; slug ]] +[@@deriving + of_yaml, + stable_record ~version:Data_intf.Academic_institution.t + ~add:[ body_md; body_html; slug ]] + +type t = [%import: Data_intf.Academic_institution.t] [@@deriving show] -let of_metadata m = metadata_to_t m ~slug:(Utils.slugify m.name) +let of_metadata m = + metadata_to_Data_intf_Academic_institution_t m ~slug:(Utils.slugify m.name) let decode (fpath, (head, body_md)) = let metadata = diff --git a/tool/ood-gen/lib/academic_testimonial.ml b/tool/ood-gen/lib/academic_testimonial.ml index 467b5c8ceb..f401968721 100644 --- a/tool/ood-gen/lib/academic_testimonial.ml +++ b/tool/ood-gen/lib/academic_testimonial.ml @@ -1,4 +1,4 @@ -open Data_intf.Academic_testimonial +type t = [%import: Data_intf.Academic_testimonial.t] [@@deriving of_yaml, show] let all () = Utils.yaml_sequence_file of_yaml "academic-testimonials.yml" @@ -7,5 +7,4 @@ let template () = include Data_intf.Academic_testimonial let all = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/blog.ml b/tool/ood-gen/lib/blog.ml index 69a57c765c..17f0703d9a 100644 --- a/tool/ood-gen/lib/blog.ml +++ b/tool/ood-gen/lib/blog.ml @@ -1,9 +1,10 @@ open Ocamlorg.Import -open Data_intf.Blog (* external RSS feeds that we aggregate - they will all be scraped by the scrape.yml workflow *) +type source = [%import: Data_intf.Blog.source] [@@deriving show] + module Source = struct type t = { id : string; @@ -16,7 +17,7 @@ module Source = struct type sources = t list [@@deriving yaml] - let all () : source list = + let all () : Data_intf.Blog.source list = let file = "planet-sources.yml" in let result = let ( let* ) = Result.bind in @@ -28,7 +29,7 @@ module Source = struct (sources |> List.map (fun { id; name; url; only_ocaml; disabled } -> { - id; + Data_intf.Blog.id; name; url; description = ""; @@ -41,6 +42,8 @@ module Source = struct Exn.Decode_error (file ^ ": " ^ msg)) end +type post = [%import: Data_intf.Blog.post] [@@deriving show] + module Post = struct type source_on_external_post = { name : string; url : string } [@@deriving yaml] @@ -58,7 +61,7 @@ module Post = struct let all_sources = Source.all () - let of_metadata ~source ~body_html m : Post.t = + let of_metadata ~source ~body_html m : Data_intf.Blog.post = { title = m.title; source = @@ -106,7 +109,9 @@ module Post = struct match Str.split (Str.regexp_string "/") fpath with | _ :: second :: _ -> ( match - List.find_opt (fun (s : source) -> s.id = second) all_sources + List.find_opt + (fun (s : Data_intf.Blog.source) -> s.id = second) + all_sources with | Some source -> Ok source | None -> Error (`Msg ("No source found for: " ^ fpath))) @@ -120,9 +125,10 @@ module Post = struct |> Result.map_error (Utils.where fpath) |> Result.map (of_metadata ~source ~body_html) - let all () : Post.t list = + let all () : Data_intf.Blog.post list = Utils.map_md_files decode "planet/*/*.md" - |> List.sort (fun (a : Post.t) (b : Post.t) -> String.compare b.date a.date) + |> List.sort (fun (a : Data_intf.Blog.post) (b : Data_intf.Blog.post) -> + String.compare b.date a.date) end module Scraper = struct @@ -136,7 +142,7 @@ module Scraper = struct let scrape_post ~source (post : River.post) = let title = River.title post in let slug = Utils.slugify title in - let source_path = "data/planet/" ^ source.id in + let source_path = "data/planet/" ^ source.Data_intf.Blog.id in let output_file = source_path ^ "/" ^ slug ^ ".md" in if not (Sys.file_exists output_file) then let url = River.link post in @@ -144,8 +150,8 @@ module Scraper = struct match (url, date) with | None, _ -> print_endline - (Printf.sprintf "skipping %s/%s: item does not have a url" source.id - slug) + (Printf.sprintf "skipping %s/%s: item does not have a url" + source.Data_intf.Blog.id slug) | _, None -> print_endline (Printf.sprintf "skipping %s/%s: item does not have a date" @@ -193,6 +199,7 @@ module Scraper = struct let scrape () = let sources = Source.all () in sources - |> List.filter (fun ({ disabled; _ } : source) -> not disabled) + |> List.filter (fun ({ disabled; _ } : Data_intf.Blog.source) -> + not disabled) |> List.iter scrape_source end diff --git a/tool/ood-gen/lib/book.ml b/tool/ood-gen/lib/book.ml index 15184d4e1f..955ac589e5 100644 --- a/tool/ood-gen/lib/book.ml +++ b/tool/ood-gen/lib/book.ml @@ -1,4 +1,17 @@ -open Data_intf.Book +type difficulty = [%import: Data_intf.Book.difficulty] [@@deriving show] + +let difficulty_of_string = function + | "beginner" -> Ok Beginner + | "intermediate" -> Ok Intermediate + | "advanced" -> Ok Advanced + | s -> Error (`Msg ("Unknown difficulty type: " ^ s)) + +let difficulty_of_yaml = function + | `String s -> difficulty_of_string s + | _ -> Error (`Msg "Expected a string for difficulty type") + +type link = [%import: Data_intf.Book.link] [@@deriving of_yaml, show] +type t = [%import: Data_intf.Book.t] [@@deriving show] type metadata = { title : string; @@ -38,6 +51,5 @@ let template () = Format.asprintf {| include Data_intf.Book let all = %a -|} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) +|} (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/changelog.ml b/tool/ood-gen/lib/changelog.ml index 8ae1409d8f..d354ef8420 100644 --- a/tool/ood-gen/lib/changelog.ml +++ b/tool/ood-gen/lib/changelog.ml @@ -1,19 +1,45 @@ -open Data_intf.Changelog - -type metadata = { - title : string; - tags : string list; - authors : string list option; - description : string option; - changelog : string option; -} -[@@deriving - of_yaml, - stable_record ~version:t ~remove:[ changelog; description ] - ~modify:[ authors ] - ~add:[ slug; changelog_html; body_html; body; date ]] - -let of_metadata m = metadata_to_t m ~modify_authors:(Option.value ~default:[]) +type release = [%import: Data_intf.Changelog.release] [@@deriving of_yaml, show] +type post = [%import: Data_intf.Changelog.post] [@@deriving of_yaml, show] +type t = [%import: Data_intf.Changelog.t] [@@deriving of_yaml, show] + +(* The OCaml.org Changelog has two categories: + + - posts - release announcements + + POSTS ===== + + These OCaml.org Changelog entries are posted automatically to various OCaml + social media accounts. + + The main accounts will automatically receive posts that (a) describe how the + user-facing surface of the tools as a whole changes and (b) empower the + reader to make better use of the OCaml Platform tools. + + These entries are represented by the RSS feed category "posts". + + Example content: - celebrating major releases or milestones - how to use new + features - which new workflows are possible now (sometimes involving releases + from multiple tools) - announcing that workarounds for bugs that are now + fixed can be retired + + Generally, these will be written together with a release announcement, or + after, and reference zero or more earlier relevant release announcements. + + RELEASE ANNOUNCEMENTS ===================== + + We also collect and broadcast release announcements for all the GitHub + repositories that directly support the OCaml Platform Tools. + + Release announcements will not go out through the main social media accounts, + but through dedicated accounts sharing releases. From these, the main OCaml + accounts can repost and comment on major releases to give more details or + highlight particular milestones. + + These entries are represented by the RSS feed category "releases". + + Generally, software engineers of the OCaml Platform will add these by opening + a pull request to mirror a release announcement that likely already happened + on discuss.ocaml.org. *) let re_date_slug = let open Re in @@ -42,53 +68,156 @@ let parse_date_from_slug s = let day = int 3 in Some (Printf.sprintf "%04d-%02d-%02d" year month day) -let decode (fname, (head, body)) = - let slug = Filename.basename (Filename.remove_extension fname) in - let metadata = - metadata_of_yaml head |> Result.map_error (Utils.where fname) - in - let body_html = - Cmarkit_html.of_doc ~safe:false - (Hilite.Md.transform - (Cmarkit.Doc.of_string ~strict:true (String.trim body))) - in - - Result.map - (fun metadata -> - let changelog_html = - match metadata.changelog with - | None -> None - | Some changelog -> - Some - (Cmarkit.Doc.of_string ~strict:true (String.trim changelog) - |> Hilite.Md.transform - |> Cmarkit_html.of_doc ~safe:false) - in - let date = - match parse_date_from_slug slug with - | Some x -> x - | None -> - failwith - "date is not present in metadata and could not be parsed from \ - slug" - in - of_metadata ~slug ~changelog_html ~body ~body_html ~date metadata) - metadata +module Releases = struct + type release_metadata = { + title : string; + tags : string list; + authors : string list option; + contributors : string list option; + description : string option; + changelog : string option; + } + [@@deriving + of_yaml, + stable_record ~version:release ~remove:[ changelog; description ] + ~modify:[ authors; contributors ] + ~add:[ slug; changelog_html; body_html; body; date ]] + + let of_release_metadata m = + release_metadata_to_release m ~modify_authors:(Option.value ~default:[]) + ~modify_contributors:(Option.value ~default:[]) + + let decode (fname, (head, body)) = + let slug = Filename.basename (Filename.remove_extension fname) in + let metadata = + release_metadata_of_yaml head |> Result.map_error (Utils.where fname) + in + let body_html = + Cmarkit_html.of_doc ~safe:false + (Hilite.Md.transform + (Cmarkit.Doc.of_string ~strict:true (String.trim body))) + in + + Result.map + (fun metadata -> + let changelog_html = + match metadata.changelog with + | None -> None + | Some changelog -> + Some + (Cmarkit.Doc.of_string ~strict:true (String.trim changelog) + |> Hilite.Md.transform + |> Cmarkit_html.of_doc ~safe:false) + in + let date = + match parse_date_from_slug slug with + | Some x -> x + | None -> + failwith + "date is not present in metadata and could not be parsed from \ + slug" + in + of_release_metadata ~slug ~changelog_html ~body ~body_html ~date + metadata) + metadata + + let all () = + Utils.map_md_files decode "changelog/releases/*/*.md" + |> List.sort (fun (a : release) b -> String.compare b.slug a.slug) +end + +module Posts = struct + type post_metadata = { + title : string; + tags : string list; + authors : string list option; + } + [@@deriving + of_yaml, + stable_record ~version:post ~modify:[ authors ] + ~add:[ slug; body_html; body; date ]] + + let of_post_metadata m = + post_metadata_to_post m ~modify_authors:(Option.value ~default:[]) + + let decode (fname, (head, body)) = + let slug = Filename.basename (Filename.remove_extension fname) in + let metadata = + post_metadata_of_yaml head |> Result.map_error (Utils.where fname) + in + let body_html = + Cmarkit_html.of_doc ~safe:false + (Hilite.Md.transform + (Cmarkit.Doc.of_string ~strict:true (String.trim body))) + in + + Result.map + (fun metadata -> + let date = + match parse_date_from_slug slug with + | Some x -> x + | None -> + failwith + "date is not present in metadata and could not be parsed from \ + slug" + in + of_post_metadata ~slug ~body ~body_html ~date metadata) + metadata + + let all () = + Utils.map_md_files decode "changelog/posts/*/*.md" + |> List.sort (fun (a : post) b -> String.compare b.slug a.slug) +end let all () = - Utils.map_md_files decode "changelog/*/*.md" - |> List.sort (fun a b -> String.compare b.slug a.slug) + let slug_of_t r = match r with Release r -> r.slug | Post p -> p.slug in + let releases = Releases.all () in + let posts = Posts.all () in + List.map (fun x -> Release x) releases @ List.map (fun x -> Post x) posts + |> List.sort (fun (a : t) b -> String.compare (slug_of_t b) (slug_of_t a)) module ChangelogFeed = struct - let create_entry (log : t) = - let content = Syndic.Atom.Html (None, log.body_html) in - let id = Uri.of_string ("https://ocaml.org/changelog/" ^ log.slug) in - let authors = (Syndic.Atom.author "Ocaml.org", []) in - let updated = Syndic.Date.of_rfc3339 (log.date ^ "T00:00:00-00:00") in - Syndic.Atom.entry ~content ~id ~authors ~title:(Syndic.Atom.Text log.title) - ~updated - ~links:[ Syndic.Atom.link id ] - () + let to_author name = Syndic.Atom.{ name; uri = None; email = None } + + let create_entry (entry : t) = + match entry with + | Release release -> + let content = Syndic.Atom.Html (None, release.body_html) in + let id = + Uri.of_string ("https://ocaml.org/changelog/release/" ^ release.slug) + in + let authors = + (Syndic.Atom.author "OCaml.org", List.map to_author release.authors) + in + let updated = + Syndic.Date.of_rfc3339 (release.date ^ "T00:00:00-00:00") + in + let categories = + [ + Syndic.Atom. + { term = "releases"; scheme = None; label = Some "Releases" }; + ] + in + Syndic.Atom.entry ~content ~id ~authors + ~title:(Syndic.Atom.Text release.title) ~updated + ~links:[ Syndic.Atom.link id ] + ~categories () + | Post post -> + let content = Syndic.Atom.Html (None, post.body_html) in + let id = Uri.of_string ("https://ocaml.org/changelog/" ^ post.slug) in + let authors = + (Syndic.Atom.author "OCaml.org", List.map to_author post.authors) + in + let updated = Syndic.Date.of_rfc3339 (post.date ^ "T00:00:00-00:00") in + let categories = + [ + Syndic.Atom.{ term = "posts"; scheme = None; label = Some "Posts" }; + ] + in + Syndic.Atom.entry ~content ~id ~authors + ~title:(Syndic.Atom.Text post.title) ~updated + ~links:[ Syndic.Atom.link id ] + ~categories () let create_feed () = let open Rss in @@ -103,5 +232,4 @@ let template () = include Data_intf.Changelog let all = %a |ocaml} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/code_example.ml b/tool/ood-gen/lib/code_example.ml index d9c596ec96..448a92b27e 100644 --- a/tool/ood-gen/lib/code_example.ml +++ b/tool/ood-gen/lib/code_example.ml @@ -1,4 +1,4 @@ -open Data_intf.Code_examples +type t = [%import: Data_intf.Code_examples.t] [@@deriving show] let all () = Utils.read_from_dir "code_examples/*.ml" @@ -11,5 +11,4 @@ let template () = include Data_intf.Code_examples let all = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/conference.ml b/tool/ood-gen/lib/conference.ml index d62730e5a7..fa073bd18b 100644 --- a/tool/ood-gen/lib/conference.ml +++ b/tool/ood-gen/lib/conference.ml @@ -1,10 +1,31 @@ -open Data_intf.Conference +type role = [%import: Data_intf.Conference.role] [@@deriving show] + +let role_of_string = function + | "chair" -> Ok `Chair + | "co-chair" -> Ok `Co_chair + | s -> Error (`Msg ("Unknown role type: " ^ s)) + +let role_of_yaml = function + | `String s -> role_of_string s + | _ -> Error (`Msg "Expected a string for role type") + +type important_date = [%import: Data_intf.Conference.important_date] +[@@deriving of_yaml, show] + +type committee_member = [%import: Data_intf.Conference.committee_member] +[@@deriving of_yaml, show] + +type presentation = [%import: Data_intf.Conference.presentation] +[@@deriving of_yaml, show] + +type t = [%import: Data_intf.Conference.t] [@@deriving of_yaml, show] type presentation_metadata = { title : string; authors : string list; link : string option; - video : string option; + watch_ocamlorg_video : string option; + youtube_video : string option; slides : string option; poster : bool option; additional_links : string list option; @@ -55,5 +76,4 @@ let template () = include Data_intf.Conference let all = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/cookbook.ml b/tool/ood-gen/lib/cookbook.ml index 136c1e1220..8ae1e565f7 100644 --- a/tool/ood-gen/lib/cookbook.ml +++ b/tool/ood-gen/lib/cookbook.ml @@ -1,4 +1,12 @@ -open Data_intf.Cookbook +type category = [%import: Data_intf.Cookbook.category] [@@deriving show] +type task = [%import: Data_intf.Cookbook.task] [@@deriving show] + +type code_block_with_explanation = + [%import: Data_intf.Cookbook.code_block_with_explanation] +[@@deriving show] + +type package = [%import: Data_intf.Cookbook.package] [@@deriving of_yaml, show] +type t = [%import: Data_intf.Cookbook.t] [@@deriving show] type task_metadata = { title : string; @@ -128,9 +136,5 @@ let top_categories = %a let tasks = %a let all = %a |ocaml} - (Fmt.brackets (Fmt.list pp_category ~sep:Fmt.semi)) - top_categories - (Fmt.brackets (Fmt.list pp_task ~sep:Fmt.semi)) - tasks - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp_category) + top_categories (Fmt.Dump.list pp_task) tasks (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/dune b/tool/ood-gen/lib/dune index c605afbf2c..4703eda561 100644 --- a/tool/ood-gen/lib/dune +++ b/tool/ood-gen/lib/dune @@ -22,4 +22,4 @@ re xmlm) (preprocess - (pps ppx_deriving_yaml ppx_stable ppx_deriving.show))) + (staged_pps ppx_import ppx_deriving_yaml ppx_stable ppx_deriving.show))) diff --git a/tool/ood-gen/lib/event.ml b/tool/ood-gen/lib/event.ml index ff18de0829..a70c2f0904 100644 --- a/tool/ood-gen/lib/event.ml +++ b/tool/ood-gen/lib/event.ml @@ -1,4 +1,26 @@ -open Data_intf.Event +type event_type = [%import: Data_intf.Event.event_type] [@@deriving show] + +let event_type_of_string = function + | "meetup" -> Ok Meetup + | "conference" -> Ok Conference + | "seminar" -> Ok Seminar + | "hackathon" -> Ok Hackathon + | "retreat" -> Ok Retreat + | s -> Error (`Msg ("Unknown event type: " ^ s)) + +let event_type_of_yaml = function + | `String s -> event_type_of_string s + | _ -> Error (`Msg "Expected a string for difficulty type") + +type location = [%import: Data_intf.Event.location] [@@deriving of_yaml, show] + +type recurring_event = [%import: Data_intf.Event.recurring_event] +[@@deriving of_yaml, show] + +type utc_datetime = [%import: Data_intf.Event.utc_datetime] +[@@deriving of_yaml, show] + +type t = [%import: Data_intf.Event.t] [@@deriving show] let recurring_event_all () : recurring_event list = Utils.yaml_sequence_file recurring_event_of_yaml "events/recurring.yml" @@ -128,7 +150,5 @@ include Data_intf.Event let recurring_event_all = %a let all = %a |} - (Fmt.brackets (Fmt.list pp_recurring_event ~sep:Fmt.semi)) - (recurring_event_all ()) - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp_recurring_event) + (recurring_event_all ()) (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/exercise.ml b/tool/ood-gen/lib/exercise.ml index 035910d7a5..9bc8c7398e 100644 --- a/tool/ood-gen/lib/exercise.ml +++ b/tool/ood-gen/lib/exercise.ml @@ -1,4 +1,16 @@ -open Data_intf.Exercise +type difficulty = [%import: Data_intf.Exercise.difficulty] [@@deriving show] + +let of_string = function + | "beginner" -> Ok Beginner + | "intermediate" -> Ok Intermediate + | "advanced" -> Ok Advanced + | s -> Error (`Msg ("Unknown difficulty type: " ^ s)) + +let difficulty_of_yaml = function + | `String s -> of_string s + | _ -> Error (`Msg "Expected a string for difficulty type") + +type t = [%import: Data_intf.Exercise.t] [@@deriving show] type metadata = { title : string; @@ -62,5 +74,4 @@ let template () = include Data_intf.Exercise let all = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/governance.ml b/tool/ood-gen/lib/governance.ml index bfe9043f93..024d7a4b1e 100644 --- a/tool/ood-gen/lib/governance.ml +++ b/tool/ood-gen/lib/governance.ml @@ -1,5 +1,53 @@ open Ocamlorg.Import -open Data_intf.Governance + +type member = [%import: Data_intf.Governance.member] [@@deriving of_yaml, show] + +type contact_kind = [%import: Data_intf.Governance.contact_kind] +[@@deriving show] + +let contact_kind_of_yaml = function + | `String "github" -> Ok GitHub + | `String "email" -> Ok Email + | `String "discord" -> Ok Discord + | `String "chat" -> Ok Chat + | x -> ( + match Yaml.to_string x with + | Ok str -> + Error + (`Msg + ("\"" ^ str + ^ "\" is not a valid contact_kind! valid options are: github, \ + email, discord, chat")) + | Error _ -> Error (`Msg "Invalid Yaml value")) + +let contact_kind_to_yaml = function + | GitHub -> `String "github" + | Email -> `String "email" + | Discord -> `String "discord" + | Chat -> `String "chat" + +type contact = [%import: Data_intf.Governance.contact] +[@@deriving of_yaml, show] + +type dev_meeting = [%import: Data_intf.Governance.dev_meeting] +[@@deriving of_yaml, show] + +type team_metadata = { + id : string; + name : string; + description : string; + contacts : contact list; + dev_meeting : dev_meeting option; [@default None] [@key "dev-meeting"] + members : member list; [@default []] + subteams : team_metadata list; [@default []] +} +[@@deriving of_yaml, stable_record ~version:Data_intf.Governance.team] + +let team_of_yaml yml = + yml |> team_metadata_of_yaml + |> Result.map team_metadata_to_Data_intf_Governance_team + +type team = [%import: Data_intf.Governance.team] [@@deriving show] type metadata = { teams : team list; @@ -27,7 +75,4 @@ let teams = %a let working_groups = %a |} - (Fmt.brackets (Fmt.list pp_team ~sep:Fmt.semi)) - t.teams - (Fmt.brackets (Fmt.list pp_team ~sep:Fmt.semi)) - t.working_groups + (Fmt.Dump.list pp_team) t.teams (Fmt.Dump.list pp_team) t.working_groups diff --git a/tool/ood-gen/lib/industrial_user.ml b/tool/ood-gen/lib/industrial_user.ml index c915c4e06f..cc1bf82ad2 100644 --- a/tool/ood-gen/lib/industrial_user.ml +++ b/tool/ood-gen/lib/industrial_user.ml @@ -1,4 +1,4 @@ -open Data_intf.Industrial_user +type t = [%import: Data_intf.Industrial_user.t] [@@deriving show] type metadata = { name : string; @@ -29,5 +29,4 @@ let template () = include Data_intf.Industrial_user let all = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/is_ocaml_yet.ml b/tool/ood-gen/lib/is_ocaml_yet.ml index 5e16d47fa6..7dde90b32e 100644 --- a/tool/ood-gen/lib/is_ocaml_yet.ml +++ b/tool/ood-gen/lib/is_ocaml_yet.ml @@ -1,4 +1,11 @@ -open Data_intf.Is_ocaml_yet +type external_package = [%import: Data_intf.Is_ocaml_yet.external_package] +[@@deriving of_yaml, show] + +type package = [%import: Data_intf.Is_ocaml_yet.package] +[@@deriving of_yaml, show] + +type category = [%import: Data_intf.Is_ocaml_yet.category] [@@deriving show] +type t = [%import: Data_intf.Is_ocaml_yet.t] [@@deriving show] type category_meta = { name : string; @@ -50,5 +57,4 @@ let template () = include Data_intf.Is_ocaml_yet let all = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/job.ml b/tool/ood-gen/lib/job.ml index 4884aba285..8f354e3a0d 100644 --- a/tool/ood-gen/lib/job.ml +++ b/tool/ood-gen/lib/job.ml @@ -1,4 +1,4 @@ -open Data_intf.Job +type t = [%import: Data_intf.Job.t] [@@deriving of_yaml, show] let all () = let job_date j = Option.value ~default:"1970-01-01" j.publication_date in @@ -37,6 +37,5 @@ let template () = Format.asprintf {| include Data_intf.Job let all = %a -|} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) +|} (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/news.ml b/tool/ood-gen/lib/news.ml index 068de981a3..568994c5f2 100644 --- a/tool/ood-gen/lib/news.ml +++ b/tool/ood-gen/lib/news.ml @@ -1,4 +1,4 @@ -open Data_intf.News +type t = [%import: Data_intf.News.t] [@@deriving show] type metadata = { title : string; @@ -31,8 +31,7 @@ let template () = Format.asprintf {| include Data_intf.News let all = %a -|} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) +|} (Fmt.Dump.list pp) (all ()) module RssFeed = struct diff --git a/tool/ood-gen/lib/opam_user.ml b/tool/ood-gen/lib/opam_user.ml index febb61516e..6496744319 100644 --- a/tool/ood-gen/lib/opam_user.ml +++ b/tool/ood-gen/lib/opam_user.ml @@ -1,4 +1,4 @@ -open Data_intf.Opam_user +type t = [%import: Data_intf.Opam_user.t] [@@deriving of_yaml, show] let all () = Utils.yaml_sequence_file of_yaml "opam-users.yml" @@ -7,5 +7,4 @@ let template () = include Data_intf.Opam_user let all = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/outreachy.ml b/tool/ood-gen/lib/outreachy.ml index 7973e3820b..4ae6a78f67 100644 --- a/tool/ood-gen/lib/outreachy.ml +++ b/tool/ood-gen/lib/outreachy.ml @@ -1,4 +1,5 @@ -open Data_intf.Outreachy +type project = [%import: Data_intf.Outreachy.project] [@@deriving of_yaml, show] +type t = [%import: Data_intf.Outreachy.t] [@@deriving of_yaml, show] let modify_project (p : project) = { @@ -18,5 +19,4 @@ let template () = include Data_intf.Outreachy let all = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/page.ml b/tool/ood-gen/lib/page.ml index 91cb821b42..90ba9af8e9 100644 --- a/tool/ood-gen/lib/page.ml +++ b/tool/ood-gen/lib/page.ml @@ -1,4 +1,4 @@ -open Data_intf.Page +type t = [%import: Data_intf.Page.t] [@@deriving show] type metadata = { title : string; @@ -26,6 +26,5 @@ let template () = Format.asprintf {| include Data_intf.Page let all = %a -|} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) +|} (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/paper.ml b/tool/ood-gen/lib/paper.ml index 1c83017069..112e8ae4f8 100644 --- a/tool/ood-gen/lib/paper.ml +++ b/tool/ood-gen/lib/paper.ml @@ -1,4 +1,5 @@ -open Data_intf.Paper +type link = [%import: Data_intf.Paper.link] [@@deriving of_yaml, show] +type t = [%import: Data_intf.Paper.t] [@@deriving show] type metadata = { title : string; @@ -24,6 +25,5 @@ let template () = Format.asprintf {| include Data_intf.Paper let all = %a -|} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) +|} (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/planet.ml b/tool/ood-gen/lib/planet.ml index 859535701a..25f3060b6a 100644 --- a/tool/ood-gen/lib/planet.ml +++ b/tool/ood-gen/lib/planet.ml @@ -1,9 +1,15 @@ open Ocamlorg.Import -open Data_intf.Planet + +type entry = BlogPost of Blog.post | Video of Vid.t +[@@deriving show { with_path = false }] + +let date_of_post = function + | BlogPost { date; _ } -> date + | Video { published; _ } -> published let all () = let external_posts = - Blog.Post.all () |> List.map (fun (p : Data_intf.Blog.Post.t) -> BlogPost p) + Blog.Post.all () |> List.map (fun (p : Blog.post) -> BlogPost p) in let videos = Video.all () |> List.map (fun (v : Data_intf.Video.t) -> Video v) @@ -17,8 +23,7 @@ let template () = include Data_intf.Planet let all = %a |ocaml} - (Fmt.brackets (Fmt.list pp_entry ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp_entry) (all ()) module GlobalFeed = struct let feed_authors (source : Data_intf.Blog.source) authors = @@ -99,7 +104,7 @@ module GlobalFeed = struct ~content:(Syndic.Atom.Html (None, content)) ()) - let entry_of_post (post : Data_intf.Blog.Post.t) = + let entry_of_post (post : Blog.post) = let content = Syndic.Atom.Html (None, post.body_html) in let url = Uri.of_string post.source.url in let source : Syndic.Atom.source = diff --git a/tool/ood-gen/lib/release.ml b/tool/ood-gen/lib/release.ml index 649e17f7f9..f6da54fc82 100644 --- a/tool/ood-gen/lib/release.ml +++ b/tool/ood-gen/lib/release.ml @@ -1,4 +1,14 @@ -open Data_intf.Release +type kind = [%import: Data_intf.Release.kind] [@@deriving show] + +let kind_of_string = function + | "compiler" -> Ok `Compiler + | s -> Error (`Msg ("Unknown release type: " ^ s)) + +let kind_of_yaml = function + | `String s -> kind_of_string s + | _ -> Error (`Msg "Expected a string for release type") + +type t = [%import: Data_intf.Release.t] [@@deriving show] type metadata = { kind : kind; @@ -76,5 +86,4 @@ let all = %a let latest = %a let lts = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - all pp latest pp lts + (Fmt.Dump.list pp) all pp latest pp lts diff --git a/tool/ood-gen/lib/resource.ml b/tool/ood-gen/lib/resource.ml index 6ee65ced48..55d1010258 100644 --- a/tool/ood-gen/lib/resource.ml +++ b/tool/ood-gen/lib/resource.ml @@ -1,4 +1,4 @@ -open Data_intf.Resource +type t = [%import: Data_intf.Resource.t] [@@deriving of_yaml, show] let all () = Utils.yaml_sequence_file of_yaml "resources.yml" @@ -10,7 +10,5 @@ include Data_intf.Resource let all = %a let featured = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - all_resources - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) + (Fmt.Dump.list pp) all_resources (Fmt.Dump.list pp) (all_resources |> List.filter (fun (r : t) -> r.featured = true)) diff --git a/tool/ood-gen/lib/rss.ml b/tool/ood-gen/lib/rss.ml index 80783f545c..10faedb128 100644 --- a/tool/ood-gen/lib/rss.ml +++ b/tool/ood-gen/lib/rss.ml @@ -8,7 +8,7 @@ let create_entries ~create_entry ?days u = Option.fold ~none:Option.some ~some days in let entries = - List.tl u |> List.map create_entry |> List.sort Syndic.Atom.descending + u |> List.map create_entry |> List.sort Syndic.Atom.descending in match List.filter_map is_fresh entries with | [] -> [ List.hd entries ] diff --git a/tool/ood-gen/lib/success_story.ml b/tool/ood-gen/lib/success_story.ml index 5e4c4be252..ff5179d69a 100644 --- a/tool/ood-gen/lib/success_story.ml +++ b/tool/ood-gen/lib/success_story.ml @@ -1,4 +1,4 @@ -open Data_intf.Success_story +type t = [%import: Data_intf.Success_story.t] [@@deriving show] type metadata = { title : string; @@ -31,5 +31,4 @@ let template () = include Data_intf.Success_story let all = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/testimonial.ml b/tool/ood-gen/lib/testimonial.ml index a9ded3dfdf..c7c1236c46 100644 --- a/tool/ood-gen/lib/testimonial.ml +++ b/tool/ood-gen/lib/testimonial.ml @@ -1,4 +1,4 @@ -open Data_intf.Testimonial +type t = [%import: Data_intf.Testimonial.t] [@@deriving of_yaml, show] let all () = Utils.yaml_sequence_file of_yaml "testimonials.yml" @@ -7,5 +7,4 @@ let template () = include Data_intf.Testimonial let all = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/tool.ml b/tool/ood-gen/lib/tool.ml index a61398783e..aa95bbb338 100644 --- a/tool/ood-gen/lib/tool.ml +++ b/tool/ood-gen/lib/tool.ml @@ -1,4 +1,17 @@ -open Data_intf.Tool +type lifecycle = [%import: Data_intf.Tool.lifecycle] [@@deriving show] + +let lifecycle_of_string = function + | "incubate" -> Ok `Incubate + | "active" -> Ok `Active + | "sustain" -> Ok `Sustain + | "deprecate" -> Ok `Deprecate + | s -> Error (`Msg ("Unknown lifecycle type: " ^ s)) + +let lifecycle_of_yaml = function + | `String s -> lifecycle_of_string s + | _ -> Error (`Msg "Expected a string for lifecycle type") + +type t = [%import: Data_intf.Tool.t] [@@deriving show] type metadata = { name : string; @@ -22,6 +35,5 @@ let template () = Format.asprintf {| include Data_intf.Tool let all = %a -|} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) +|} (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/tool_page.ml b/tool/ood-gen/lib/tool_page.ml index d4b0d8c065..2354c7947c 100644 --- a/tool/ood-gen/lib/tool_page.ml +++ b/tool/ood-gen/lib/tool_page.ml @@ -1,5 +1,11 @@ open Ocamlorg.Import -open Data_intf.Tool_page + +type toc = [%import: Data_intf.Tool_page.toc] [@@deriving of_yaml, show] + +type contribute_link = [%import: Data_intf.Tool_page.contribute_link] +[@@deriving of_yaml, show] + +type t = [%import: Data_intf.Tool_page.t] [@@deriving show] type metadata = { id : string; @@ -45,5 +51,4 @@ let template () = include Data_intf.Tool_page let all = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) + (Fmt.Dump.list pp) (all ()) diff --git a/tool/ood-gen/lib/tutorial.ml b/tool/ood-gen/lib/tutorial.ml index 5affa06596..9ae7239273 100644 --- a/tool/ood-gen/lib/tutorial.ml +++ b/tool/ood-gen/lib/tutorial.ml @@ -1,5 +1,40 @@ open Ocamlorg.Import -open Data_intf.Tutorial + +type section = [%import: Data_intf.Tutorial.section] [@@deriving show] + +let section_of_string = function + | "getting-started" -> Ok GetStarted + | "language" -> Ok Language + | "platform" -> Ok Platform + | "guides" -> Ok Guides + | s -> Error (`Msg ("Unknown section: " ^ s)) + +type toc = [%import: Data_intf.Tutorial.toc] [@@deriving show] + +type contribute_link = [%import: Data_intf.Tutorial.contribute_link] +[@@deriving of_yaml, show] + +type banner = [%import: Data_intf.Tutorial.banner] [@@deriving of_yaml, show] + +type external_tutorial = [%import: Data_intf.Tutorial.external_tutorial] +[@@deriving of_yaml, show] + +type recommended_next_tutorials = + [%import: Data_intf.Tutorial.recommended_next_tutorials] +[@@deriving of_yaml, show] + +type prerequisite_tutorials = + [%import: Data_intf.Tutorial.prerequisite_tutorials] +[@@deriving of_yaml, show] + +type search_document_section = + [%import: Data_intf.Tutorial.search_document_section] +[@@deriving of_yaml, show] + +type search_document = [%import: Data_intf.Tutorial.search_document] +[@@deriving show] + +type t = [%import: Data_intf.Tutorial.t] [@@deriving show] type metadata = { id : string; @@ -55,7 +90,7 @@ let decode (fpath, (head, body_md)) = in let section = List.nth (String.split_on_char '/' fpath) 1 - |> Section.of_string + |> section_of_string |> Result.get_ok ~error:(fun (`Msg msg) -> Exn.Decode_error (fpath ^ ":" ^ msg)) in @@ -118,7 +153,6 @@ include Data_intf.Tutorial let all = %a let all_search_documents = %a |} - (Fmt.brackets (Fmt.list pp ~sep:Fmt.semi)) - (all ()) - (Fmt.brackets (Fmt.list pp_search_document ~sep:Fmt.semi)) + (Fmt.Dump.list pp) (all ()) + (Fmt.Dump.list pp_search_document) (TutorialSearch.all ()) diff --git a/tool/ood-gen/lib/vid.ml b/tool/ood-gen/lib/vid.ml new file mode 100644 index 0000000000..8f0ac7128b --- /dev/null +++ b/tool/ood-gen/lib/vid.ml @@ -0,0 +1,2 @@ +type t = [%import: Data_intf.Video.t] [@@deriving yaml, show] +type video_list = t list [@@deriving yaml, show] diff --git a/tool/ood-gen/lib/video.ml b/tool/ood-gen/lib/video.ml index a9e4817a3b..64ba8b1224 100644 --- a/tool/ood-gen/lib/video.ml +++ b/tool/ood-gen/lib/video.ml @@ -1,7 +1,3 @@ -open Data_intf.Video - -type video_list = t list [@@deriving yaml, show] - let all () = Youtube.all () @ Watch.all () let template () = @@ -9,7 +5,7 @@ let template () = include Data_intf.Video let all =%a |ocaml} - pp_video_list (all ()) + Vid.pp_video_list (all ()) let scrape () = Youtube.scrape "data/video-youtube.yml"; diff --git a/tool/ood-gen/lib/watch.ml b/tool/ood-gen/lib/watch.ml index 55e8da4f1d..6f43a0359d 100644 --- a/tool/ood-gen/lib/watch.ml +++ b/tool/ood-gen/lib/watch.ml @@ -1,14 +1,11 @@ open Ocamlorg.Import -open Data_intf.Video - -type video_list = t list [@@deriving yaml, show] let all () = let ( let* ) = Result.bind in let videos = let file = "video-watch.yml" in let* yaml = Utils.yaml_file file in - yaml |> video_list_of_yaml |> Result.map_error (Utils.where file) + yaml |> Vid.video_list_of_yaml |> Result.map_error (Utils.where file) in Result.get_ok ~error:(fun (`Msg msg) -> Exn.Decode_error msg) videos @@ -28,7 +25,7 @@ let get_string_or_none = function `String s -> s | _ -> "" let of_json json = { - title = Ezjsonm.find json [ "name" ] |> Ezjsonm.get_string; + Vid.title = Ezjsonm.find json [ "name" ] |> Ezjsonm.get_string; description = Ezjsonm.find json [ "description" ] |> get_string_or_none; url = Ezjsonm.find json [ "url" ] |> Ezjsonm.get_string; thumbnail = @@ -44,7 +41,7 @@ let of_json json = let watch_to_yaml t = `O [ - ("title", `String t.title); + ("title", `String t.Vid.title); ("description", `String t.description); ("url", `String t.url); ("thumbnail", `String t.thumbnail); @@ -92,7 +89,7 @@ let get_all_videos () = let scrape yaml_file = let watch = get_all_videos () - |> List.stable_sort (fun w1 w2 -> String.compare w1.title w2.title) + |> List.stable_sort (fun w1 w2 -> String.compare w1.Vid.title w2.Vid.title) in let yaml = to_yaml watch in let output = diff --git a/tool/ood-gen/lib/youtube.ml b/tool/ood-gen/lib/youtube.ml index 601cf87e5b..86c9e2a45b 100644 --- a/tool/ood-gen/lib/youtube.ml +++ b/tool/ood-gen/lib/youtube.ml @@ -1,5 +1,18 @@ open Ocamlorg.Import -open Data_intf.Video + +let to_yaml video = + match Vid.to_yaml video with + | `O u -> `O (List.filter (( <> ) ("description", `String "")) u) + | x -> x + +let add_key_default k v = function + | `O u when u |> List.split |> fst |> List.mem k |> not -> + prerr_endline k; + `O ((k, v) :: u) + | x -> x + +let of_yaml yml = + yml |> add_key_default "description" (`String "") |> Vid.of_yaml type kind = Playlist | Channel @@ -40,8 +53,6 @@ let source_to_url { kind; id; _ } = let source_to_id { kind; id; _ } = Printf.sprintf "yt:%s:%s" (kind_to_string kind) id -type video_list = t list [@@deriving yaml, show] - type tag = | Entry | Title of string @@ -103,7 +114,7 @@ let video_opt source = function Some author_uri ) -> Some { - title; + Vid.title; url; thumbnail; description; @@ -142,14 +153,14 @@ let all () = let videos = let file = "video-youtube.yml" in let* yaml = Utils.yaml_file file in - yaml |> video_list_of_yaml |> Result.map_error (Utils.where file) + yaml |> Vid.video_list_of_yaml |> Result.map_error (Utils.where file) in Result.get_ok ~error:(fun (`Msg msg) -> Exn.Decode_error msg) videos module VideoSet = Set.Make (struct - type nonrec t = t + type nonrec t = Vid.t - let compare a b = compare a.url b.url + let compare a b = compare a.Vid.url b.Vid.url end) let scrape yaml_file = @@ -170,8 +181,8 @@ let scrape yaml_file = |> Seq.filter (fun video -> (not src.only_ocaml) || String.( - is_sub_ignore_case "ocaml" video.title - || is_sub_ignore_case "ocaml" video.description))) + is_sub_ignore_case "ocaml" video.Vid.title + || is_sub_ignore_case "ocaml" video.Vid.description))) |> VideoSet.of_seq |> Result.ok in match fetched with @@ -179,8 +190,8 @@ let scrape yaml_file = let yaml = VideoSet.union fetched scraped |> VideoSet.to_seq |> List.of_seq - |> List.sort (fun a b -> compare b.published a.published) - |> video_list_to_yaml + |> List.sort (fun a b -> compare b.Vid.published a.Vid.published) + |> Vid.video_list_to_yaml in let output = Yaml.pp Format.str_formatter yaml; diff --git a/tool/tailwind/dune b/tool/tailwind/dune index 02f62f861d..bbcbeff0f5 100644 --- a/tool/tailwind/dune +++ b/tool/tailwind/dune @@ -2,40 +2,40 @@ (target tailwindcss-linux-x64) (action (progn - (run - curl - -sLO - https://github.com/tailwindlabs/tailwindcss/releases/download/v3.3.6/%{target}) + (with-stdout-to + %{target} + (bash + "cat 2> /dev/null < $(which tailwindcss) || curl -#fSL https://github.com/tailwindlabs/tailwindcss/releases/download/v3.3.6/%{target}")) (run chmod +x %{target})))) (rule (target tailwindcss-linux-arm64) (action (progn - (run - curl - -sLO - https://github.com/tailwindlabs/tailwindcss/releases/download/v3.3.6/%{target}) + (with-stdout-to + %{target} + (bash + "cat 2> /dev/null < $(which tailwindcss) || curl -#fSL https://github.com/tailwindlabs/tailwindcss/releases/download/v3.3.6/%{target}")) (run chmod +x %{target})))) (rule (target tailwindcss-macos-x64) (action (progn - (run - curl - -sLO - https://github.com/tailwindlabs/tailwindcss/releases/download/v3.3.6/%{target}) + (with-stdout-to + %{target} + (bash + "cat 2> /dev/null < $(which tailwindcss) || curl -#fSL https://github.com/tailwindlabs/tailwindcss/releases/download/v3.3.6/%{target}")) (run chmod +x %{target})))) (rule (target tailwindcss-macos-arm64) (action (progn - (run - curl - -sLO - https://github.com/tailwindlabs/tailwindcss/releases/download/v3.3.6/%{target}) + (with-stdout-to + %{target} + (bash + "cat 2> /dev/null < $(which tailwindcss) || curl -#fSL https://github.com/tailwindlabs/tailwindcss/releases/download/v3.3.6/%{target}")) (run chmod +x %{target})))) (rule @@ -81,3 +81,8 @@ (alias (name default) (deps tailwindcss)) + +(install + (section bin) + (package tailwindcss) + (files tailwindcss))