Attn: Development Editor, Latest OCaml Weekly News
Alan Schmitt <[email protected]>
| Newsgroups | gmane.comp.lang.caml.inria |
|---|---|
| Message-ID | <[email protected]> |
Hello
Here is the latest OCaml Weekly News, for the week of January 02 to 09,
2024.
Table of Contents
─────────────────
Odoc module index bookmarklet
create-melange-app 1.0.0 - A CLI for quickly becoming productive with Melange
What’s possible with Melange
Ocaml-ts-mode - Emacs ocaml major mode using tree sitter
Using Menhir to parse into idiomatic JS (TypeScript) structures
Play with project-wide occurrences for OCaml!
New release of Menhir (20231231)
Ocsigen: summary of recent releases
sarif 0.1.0 - Static Analysis Results Interchange Format (SARIF) For OCaml
Other OCaml News
Old CWN
Odoc module index bookmarklet
═════════════════════════════
Archive:
<https://discuss.ocaml.org/t/odoc-module-index-bookmarklet/13780/1>
Yawar Amin announced
────────────────────
Hello, I made a [bookmarklet] that injects an index of a module’s
contents into the sidebar of an _odoc-generated module documentation_
page. For example, if you go to <https://aantron.github.io/dream/> ,
and run the bookmarklet, you will see:
<https://global.discourse-cdn.com/business7/uploads/ocaml/optimized/2X/b/b8ff2875a69e16df70772fe76e04f8bad334bc5d_2_1380x624.png>
[bookmarklet] <https://yawaramin.github.io/bookmarklets/#h2-odoc-idx>
create-melange-app 1.0.0 - A CLI for quickly becoming productive with Melange
═════════════════════════════════════════════════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/ann-create-melange-app-1-0-0-a-cli-for-quickly-becoming-productive-with-melange/13794/1>
Dillon Mulroy announced
───────────────────────
Hello y’all 👋
I have been working on creating a scaffolding tool aimed at enabling
JavaScript and TypeScript developers to quickly become familiar and
productive with OCaml, ReasonML, and Melange. The developer
experience, tooling, and project setup is opinionated and meant to be
familiar and friendly for folks coming from that ecosystem.
So, without further ado, I’m excited to announce create-melange-app,
1.0.0!
Get started by simply running `npm create melange-app@latest' and
completing the questions that the CLI will guide you through.
Project setup:
<https://global.discourse-cdn.com/business7/uploads/ocaml/optimized/2X/f/f933ddbdd7f1a8471f82d58ded774eeeffc98800_2_900x932.jpeg>
Scaffolding:
<https://global.discourse-cdn.com/business7/uploads/ocaml/optimized/2X/c/c82f71d8455efb6d4e2de8275f7aecba72780294_2_900x564.jpeg>
<https://global.discourse-cdn.com/business7/uploads/ocaml/optimized/2X/9/929f373bee8384d50d017200f73c354e61ef916c_2_900x534.jpeg>
✨Your new Melange app ✨
<https://global.discourse-cdn.com/business7/uploads/ocaml/optimized/2X/e/eb0987302d99dfdb0ae87bf1bf371856fe27624d_2_900x576.jpeg>
<https://global.discourse-cdn.com/business7/uploads/ocaml/optimized/2X/6/6b3a945d63c3664a792894366e8ead786ef6b723_2_900x792.jpeg>
You can find the code/projected generated in this example here:
<https://github.com/dmmulroy/create-melange-app-example>
I’ve tried to take great care to provide as much helpful information
for developers unfamiliar with our ecosystem as possible. You’ll find
many of the scaffolded files commented with explanations, examples,
and additional resources aimed at quickly becoming productive with
OCaml, ReasonML, and Melange.
*Looking forward 👀*
I have a lot of ideas around making bindings easier and more pleasant
to write for manage, along with some delightful ways to integrate them
into CMA.
But first…
We’re rewriting to native OCaml using [MintTea]! Currently
`create-melange-app' is written using Melange and [Ink], a library for
rendering React components too the terminal.
When I started CMA, OCaml didn’t have a great TUI story for easily
making delightful experiences (plus I wanted an excuse to go deeper
with Melange, and doesn’t a CLI written with OCaml and React sound
ridiculous? 😂)
I would love for CMA itself to be a great OSS project for beginners
with OCaml to get involved with and learn with and I’m aiming to bring
as many people along for that ride as I can :)
You can follow my development of CMA on [my twitch channel] where I
live stream OCaml content every M-F 7am - 10am ET
Thanks y’all! 🐫
[MintTea] <https://github.com/leostera/minttea>
[Ink] <https://github.com/vadimdemedes/ink>
[my twitch channel] <https://twitch.tv/dmmulroy>
What’s possible with Melange
════════════════════════════
Archive:
<https://discuss.ocaml.org/t/whats-possible-with-melange/13806/1>
David Sancho announced
──────────────────────
Hi
Since dune got the integration with Melange (and Ahrefs migrated to
Melange
<https://discuss.ocaml.org/t/ahrefs-is-now-built-with-melange/12107>)
I wanted to write about the benefits of using it.
I wrote a blog post comparing Melange with the previous compiler
(BuckleScript/ReScript) and what’s possible. I tried to be objetive
and focus only on the technical parts of it.
The link to the post is:
<https://sancho.dev/blog/whats-possible-with-melange>
Hope you like it, and feel free to ask anything!
Ocaml-ts-mode - Emacs ocaml major mode using tree sitter
════════════════════════════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/ocaml-ts-mode-emacs-ocaml-major-mode-using-tree-sitter/13807/1>
Malcolm announced
─────────────────
This weekend I got interested in emacs major modes based on
treesitter, so I decided to implement `ocaml-ts-mode'. The code can be
found here:
<https://github.com/terrateamio/ocaml-ts-mode>
It was actually very easy thanks to the hard work others have done in
creating the treesitter grammar.
It supports:
• Syntax highlighting of `.ml' and `.mli' files.
• Initial indentation support (this is probably currently broken in
multiple places)
• `C-c C-a' - Switch between `.ml' and `.mli' files for a module.
This is less feature rich than Tuareg mode, so I don’t know if it
replaces it. If anything, maybe it could be integrated into tuareg
mode.
I have no experience writing elisp so this probably has obvious
mistakes. Contributions welcome!
Enjoy!
Malcolm then added
──────────────────
Whoops, in my excitement learning about treesitter I didn’t notice
that there already is an ocaml-ts-mode. That one is probably the
preferred one to use. I’ll probably direct any of my development
towards it. But learning how to make a major mode was a fun
experience.
Using Menhir to parse into idiomatic JS (TypeScript) structures
═══════════════════════════════════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/using-menhir-to-parse-into-idiomatic-js-typescript-structures/13809/1>
Shon announced
──────────────
Hello and Happy New Year!
As we all know, despite being named an [Objective Categorical Abstract
Machine Language], OCaml is Obviously a Completely Awesome [Meta
Language](<https://en.wikipedia.org/wiki/ML_(programming_language)>).
The awesomeness is founded on the wonderful language, but obviously
completed by the extraordinary ecosystem of tools and techniques that
take life in that language. :stuck_out_tongue_winking_eye:
This is a note to share a solution I hacked together using a handful
of these awesome tools in our lovely language, but also a request for
any suggestions on a more elegant solution to the problem posed.
[Objective Categorical Abstract Machine Language]
<https://en.wikipedia.org/wiki/Caml>
The Problem
╌╌╌╌╌╌╌╌╌╌╌
I wanted to use Menhir and Sedlex to write a fault-tolerant,
incremental parser for a preexisting project that has an intermediate
representation (IR), and a bunch of other tools, written in
TypeScript.
Non-solutions
╌╌╌╌╌╌╌╌╌╌╌╌╌
Unfortunately, achieving this outcome was not quite as simple as
adding a `(mode js)' to dune to have the generated parser compiled by
[Js_os_ocaml (Jsoo) ]. Of course, that *does* work like a charm, and
if we could justify rewriting everything in OCaml, we’d be able to
produce JS easy as pie. But for interop with the existing TypeScript
code this won’t fly. We need to parse into JS objects that represent
the IR in a human-readable way, ideally matching our existing
TypeScript types, but Jsoo gives something like this.
┌────
│ > parser.parse('def foo(a,b) = 123')
│ [ 0, [ 0, [ 0, [Array], [Array] ], 0 ] ]
└────
My next thought was to use Melange: it seems to be a great project
with a lot of excellent work going in to it, and, iiuc, its purpose is
precisely to compile OCaml into idiomatic(ish) JS. But I hit a road
block right away, which led me to ask
<https://discuss.ocaml.org/t/what-are-the-limits-and-prerequisites-of-using-dependencies-with-melange/13688>
and to try something else.
[Js_os_ocaml (Jsoo) ]
<https://ocsigen.org/js_of_ocaml/latest/manual/overview>
A Solution
╌╌╌╌╌╌╌╌╌╌
Fortunately, the wealth of shining jewels-of-tools in the OCaml
ecosystem made this short work. The solution I ended up with is hacky
as heck, but its doing what I needed:
• I define our types using the excellent [atd].
• I generate OCaml and TypeScript representations of the types, along
with JSON serializers, via a dune config like
┌────
│ (library
│ (public_name lang_ir)
│ (libraries atdgen))
│
│ ;; The OCaml ser/de-serializers
│ (rule
│ (targets lang_ir_j.ml
│ lang_ir_j.mli)
│ (deps lang_ir.atd)
│ (action (run atdgen -j -j-std %{deps})))
│
│ ;; The OCaml types
│ (rule
│ (targets lang_ir_t.ml
│ lang_ir_t.mli)
│ (deps lang_ir.atd)
│ (action (run atdgen -t %{deps})))
│
│ ;; The TypeScript types and ser/de
│ (rule
│ (targets lang_ir.ts)
│ (deps lang_ir.atd)
│ (action (run atdts %{deps})))
│
│ ;; Conversion of the TypeScript into vanilla JS so I can test it with node
│ (rule
│ (targets lang_ir.js)
│ (deps lang_ir.ts)
│ (action (run npx tsc %{deps})))
└────
• I use menhir and sedlex to define a parser that produces inhabitants
of the OCaml types generated in `lang_ir_t.ml'. (Working out the
incremental, fault-tolerant parsing was its own exhilarating side
quest, but I’ll save a report on that for it’s own post.)
• Then I use Jsoo to run the parser in JS and then serialize its
optimized but inscritable representation into the JSON dictated by
atd:
┌────
│ open Lang_parser_lib
│
│ open Js_of_ocaml
│
│ (* Export functions *)
│ (* See https://ocsigen.org/js_of_ocaml/latest/manual/rev-bindings *)
│ let _ =
│ Js.export_all
│ (object%js
│ method parse s =
│ let lexbuf = Sedlexing.Utf8.from_string s in
│ match parse lexbuf with (* run the parser *)
│ | Some t -> Lang_ir.Quint_ir_j.string_of_t t (* produce a JSON string
│ from the result*)
│ | None -> ""
│ end)
└────
• And, finally, I make a little `wrapper.js' that invokes the
atd-generated deserializer to parse into the TypeScript
representation:
┌────
│ var ir = require('./_build/default/ir/lang_ir.js')
│ var parser = require('./_build/default/js/lang_parser.bc.js')
│
│ exports.parse = function (s) {
│ return ir.readT(JSON.parse(parser.parse(s)))
│ }
└────
[atd] <https://github.com/ahrefs/atd>
The result
╌╌╌╌╌╌╌╌╌╌
I now can use the wrapper script to parse into the nice TypeScript
(compatible) structures I need:
┌────
│ [me@comp mparsing]$ node
│ > var p = require('./wrapper.js')
│ undefined
│ > p.parse("def foo(a,b) = 123")
│ [
│ {
│ loc: { start_: [Object], end_: [Object] },
│ v: { name: 'foo', params: [Array], body: [Object] }
│ }
│ ]
└────
I have three hopes for this post:
1. I hope to contribute yet another note celebrating the virtues of
our extraordinary programming language ecosystem.
2. I hope it might be useful for others who need to solve similar
problems.
3. I hope there is a more elegant way to achieve this result (namely,
without having to go through serialization) and that one of y’all
can point the way.
:heart: :camel:
Play with project-wide occurrences for OCaml!
═════════════════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/ann-preview-play-with-project-wide-occurrences-for-ocaml/13814/1>
vds announced
─────────────
Hi fellow camelers 👋, I am very pleased to announce that every one
can now try the upcoming project-wide occurrences feature for Merlin
and OCaml-LSP.
This feature involves changes to multiple packages such as `ocaml',
`merlin', `ocaml-lsp' and `dune' so we decided to prepare a custom
opam repository to make it easy for adventurous people to install the
feature, play with it, and most-importantly… break it ! We hope you
will have as much fun querying around your codebases as we do :-)
Requirements for this preview:
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
• Have projects compatible with /OCaml 4.14.2/.
• These projects build with /Dune/. (The tools themselves are
build-system agnostic, but this preview only include rules for
Dune.)
• You use an /LSP-based editor plugin/. (We do plan to bring basic
support to the vanilla `emacs' and `vim' modes for Merlin.)
What the feature does…
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
• ✅ Returns every *usages* of types, values, constructors and labels
in `ml' and `mli' files in the workspace
• ✅ Returns direct usages of modules (like `M' in `include M')
• ✅ Can be called on any such usage of a value or on its *definition*
itself
…what is does not do yet:
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
• ❌ Return *declarations* related to searched values in both *ml* and
*mli* files. This will come in a second iteration.
• ❌ Occurrences of modules appearing in paths: like `M' and `N' in
`M.N.P'. This will also arrive later.
• ⚠️ Renaming is experimental and not as smart as one would expect
(with regard to punning and other syntactic tricks).
…and known caveats:
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
• ⚠️ Interaction with PPX might give unexpected results depending on
the specifics of the PPX.
• ⚠️ Values whose definition cannot be determined statically (like
items of a first-class module) won’t be searched project-wide. For
the same reason, walues coming from libraries that do not install
their `cmt' files won’t be searched project-wide.
Demo
╌╌╌╌
In the following demo, the feature is used to rename a symbol in
Merlin. Since the name appears in one *declaration*, this last
occurrence still needs to be replaced by hand for the build to
succeed:
<https://global.discourse-cdn.com/business7/uploads/ocaml/original/2X/5/5f9380fcc7e841c54e018a390946eaa801ff4241.gif>
Setup
╌╌╌╌╌
You can find detailed setup instruction in the [custom opam
repository]. In short:
1. Add the repository to your opam installation: `opam repo add index
https://github.com/voodoos/opam-repository-index.git'
2. Create a switch (global or local) with the `+index' ocaml variant:
`opam switch create --repositories=default,index 4.14.2+index'
3. Install `merlin', `ocaml-lsp' and the indexer: `opam install
indexing-tools'
4. Build the index with your project: `dune build @ocaml-index
@your-usual-target-maybe-install-or-all --watch'
References and renaming queries should return result on the entire
workspace.
[custom opam repository]
<https://github.com/voodoos/opam-repository-index>
Feedback
╌╌╌╌╌╌╌╌
Please do not hesitate to share any feedback on the feature here or by
[opening an issue on the repository] :slightly_smiling_face:
[opening an issue on the repository]
<https://github.com/voodoos/opam-repository-index/issues>
New release of Menhir (20231231)
════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/ann-new-release-of-menhir-20231231/13816/1>
François Pottier announced
──────────────────────────
It is my pleasure to announce a new version of Menhir, 20231231. It
should be available now:
┌────
│ opam update
│ opam install menhir.20231231
└────
The main new features are as follows:
• The new command line switch `--unparsing' (which must be used in
conjunction with `--table') causes Menhir to generate an unparsing
API. In short, unparsing is the process of transforming abstract
syntax trees back into text. The unparsing API is intended to help
users write correct unparsers, but does not automate the whole
process.
For more details, please see the paper [Correct, Fast LR(1)
Unparsing].
The unparsing API requires linking with the library `MenhirCST', and
requires OCaml 4.08.
• Attributes can now be attached with a production. (In previous
versions of Menhir, attributes could be attached only with a symbol,
with a specific occurrence of a symbol in the right-hand side of a
production, or with the whole grammar.) This is achieved by letting
one or more attributes appear immediately after the semantic action.
During the two grammar transformation phases (expansion of
parameterized nonterminal symbols and elimination of `%inline'
nonterminal symbols), the `[@name]' attributes attached with
productions receive special treatment, so as to allow each
production to receive a unique name.
[Correct, Fast LR(1) Unparsing]
<http://cambium.inria.fr/~fpottier/publis/pottier-unparsing-2024.pdf>
Ocsigen: summary of recent releases
═══════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/ocsigen-summary-of-recent-releases/13817/1>
Vincent Balat announced
───────────────────────
We do not announce very often our releases on this forum. Here is a
roundup of recent releases to make amends.
Many releases of [Js_of_ocaml] last year, with important features like
the support of OCaml 5 effects, global dead-code elimination, support
for modern JavaScript and [a huge list of improvements and fixes].
There is now also a new backend for js_of_ocaml, [Wasm_of_ocaml]
written by @vouillon, to compile to WebAssembly. It can be used as a
replacement for js_of_ocaml with very few changes.
[Eliom], the OCaml Web framework, has now reached version 10.2.
Amongst the most recent changes:
• The Dune-based build system is now the default one for client-server
apps
• compatibility with OCaml 5
• Reactive programming: Update to recent versions of js_of_ocaml,
which support weak pointers
• Documentation improvements
An [experimental version] is also available to build WASM applications
with wasm_of_ocaml
[Ocsigen-Start] version 6.1
• removes a dependency on Ocamlnet to make it compatible with OCaml 5.
No default email function is now provided. Warning: this might be a
regression if you use the default email-sending function.
• updates the dune-based build system
[Tyxml] 4.6 was released with [fixes] on some tags and options.
[Lwt] reach version [5.7]
Several maintenance releases of [Ocsigen-Toolkit]
The Ocsigen team wishes you a happy new year!
[Js_of_ocaml] <http://ocsigen.org/js_of_ocaml>
[a huge list of improvements and fixes]
<https://github.com/ocsigen/js_of_ocaml/blob/master/CHANGES.md>
[Wasm_of_ocaml] <https://github.com/ocaml-wasm/wasm_of_ocaml>
[Eliom] <http://ocsigen.org/eliom>
[experimental version] <https://github.com/ocsigen/eliom/pull/767>
[Ocsigen-Start] <http://ocsigen.org/ocsigen-start>
[Tyxml] <http://ocsigen.org/tyxml>
[fixes] <https://github.com/ocsigen/tyxml/releases>
[Lwt] <http://ocsigen.org/lwt>
[5.7] <https://github.com/ocsigen/lwt/releases/tag/5.7.0>
[Ocsigen-Toolkit] <http://ocsigen.org/ocsigen-toolkit>
sarif 0.1.0 - Static Analysis Results Interchange Format (SARIF) For OCaml
══════════════════════════════════════════════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/ann-sarif-0-1-0-static-analysis-results-interchange-format-sarif-for-ocaml/13821/1>
Geoffrey Borough announced
──────────────────────────
Hi folks, I announce the initial release of sarif version 0.1.0, a
library for processing and validating the SARIF format. If you are
familiar with static analysis and/or code scanner like Semgrep or Snyk
etc, SARIF is one of the output format that people generate and share
after scanning, the specification itself is quite big and convoluted.
My motivation for making this library is that there seems to be no
definitive library for SARIF in the OCaml ecosystem, and even
companies like Semgrep relies on some python glue code to generate the
format. Given OCaml’s importance in the static analysis scene I
thought it would be nice if this gets over the line :slight_smile:
Code: <https://github.com/gborough/sarif>
Documentation:
<https://gborough.github.io/sarif/sarif/sarif/index.html> (Package
available very soon in opam-repository pending PR approval)
Have a nice day!
Other OCaml News
════════════════
From the ocaml.org blog
───────────────────────
Here are links from many OCaml blogs aggregated at [the ocaml.org
blog].
• [Parsing with Binary String Pattern Matching]
[the ocaml.org blog] <https://ocaml.org/blog/>
[Parsing with Binary String Pattern Matching]
<https://practicalocaml.com/parsing-with-binary-string-pattern-matching/>
Old CWN
═══════
If you happen to miss a CWN, you can [send me a message] and I’ll mail
it to you, or go take a look at [the archive] or the [RSS feed of the
archives].
If you also wish to receive it every week by mail, you may subscribe
to the [caml-list].
[Alan Schmitt]
[send me a message] <mailto:[email protected]>
[the archive] <https://alan.petitepomme.net/cwn/>
[RSS feed of the archives] <https://alan.petitepomme.net/cwn/cwn.rss>
[caml-list] <https://sympa.inria.fr/sympa/info/caml-list>
[Alan Schmitt] <https://alan.petitepomme.net/>