[new release] atd (11 packages) (4.0.0)#29552
Merged
mseri merged 5 commits intoocaml:masterfrom Mar 18, 2026
Merged
Conversation
CHANGES: * Build: Dune >= 3.18 (April 2025) is now required to build the ATD tools from source. (ahrefs/atd#445) * atdcat: read from stdin when no input file is given, like `cat`. * ATD: **Experimental.** Module support via new `from ... import ...` syntax. Types to be used must be listed explicitly; the full syntax is: from module.path <annots> [as alias] import type1 <annots>, type2, ... Key properties: - Imported types must be listed explicitly (e.g. `from mylib import date, status`). - Supported languages: OCaml (atdml, not atdgen), Python (atdpy), TypeScript (atdts) - Parameterized types declare their arity: `from mylib import 'a list_ne`. - The arity of each imported type is enforced at all use-sites within the importing file. - Aliases are plain names without annotations: `from foo as f import t`. - Language-specific name annotations go on the module path: `<python name="...">` for atdpy, `<ts name="...">` for atdts, `<ocaml name="...">` for atdml. - atdpy: alias names that are Python keywords are automatically suffixed with `_` (e.g. alias `class` → `class_` in generated code). - atdts: Dotted module paths in `import` declarations are now mapped to path-separator form in the generated TypeScript import path. For example, `import long.module.path` generates `import * as path from "./long/module/path"` rather than `"./path"`. - A warning is printed to stderr when an imported type name is never referenced in any type expression. Examples: (* Import specific types from a module *) from mylib.common import date, status (* Import with alias *) from long.module.path as ext import tag (* Override OCaml module name *) from mylib.common <ocaml name="Mylib_common"> import date * atdml: **Experimental.** New tool. Generates a single self-contained OCaml module (`.ml` + `.mli`) from a single `.atd` file, with JSON support via `Yojson.Safe.t`. No separate runtime library is required; the runtime helpers are inlined into each generated `.ml`. Atdml is the recommended successor to atdgen for OCaml JSON support. Supported features: - All primitive ATD types: `unit`, `bool`, `int`, `float`, `string` - `abstract` type, represented as `Yojson.Safe.t` - `'a list`, `'a option`, `'a nullable` - Tuples: `('a * 'b * ...)` - Records, including required fields, optional fields (`?foo`), and with-default fields (`~foo`) with implicit or explicit defaults (`<ocaml default="...">`) - `<ocaml field_prefix="pre_">` on record types: prepends the given prefix to all OCaml record field names while keeping the labeled arguments of `create_` unprefixed (e.g. `create_point ~x ~y () : point`). JSON field names are unaffected. - Classic sum types (regular OCaml variants) and polymorphic variants (`<ocaml repr="poly">`) - Parametric types - Mutually recursive types (detected automatically via topological sort; `and` is used only when strictly necessary) - `wrap` construct with `<ocaml module="M">` or explicit `<ocaml t="..." wrap="..." unwrap="...">` - JSON adapters via `<json adapter.ocaml="M">` (module providing `normalize` and `restore`) or `<json adapter.to_ocaml="..." adapter.from_ocaml="...">` (inline expressions); supported on sum types and records - `<json name="...">` to override JSON field or constructor names - `<ocaml name="...">` to rename variant constructors in OCaml - `<ocaml attr="...">` to attach ppx attributes (e.g. `[@@deriving show]`) to generated type definitions - `<ocaml private>` on any type definition forces `private` in the generated `.mli`; `<ocaml public>` on a primitive alias suppresses the default `private`, making the alias transparent to callers - Unparameterized aliases of primitive types (`unit`, `bool`, `int`, `float`, `string`) are generated as `private` in the `.mli`, preventing direct construction outside the module. A constructor function `create_email : string -> email` is generated (also exposed as `val create` in submodule `Email`). Coerce back with `:>` (e.g. `(x :> string)`). - `<doc text="...">` documentation annotations, translated into ocamldoc `(** ... *)` comments in the generated code; supported on type definitions, record fields, variant constructors, and module-level head annotations - Automatic renaming of ATD type names that conflict with OCaml keywords or with the `foo_of_yojson`/`yojson_of_foo` naming scheme - Automatic renaming of record fields and variant constructors that conflict with OCaml keywords (e.g. `end` → `end_`) - `(string * 'a) list <json repr="object">`: encode association lists as JSON objects `{"key": value, ...}` rather than arrays - Graceful handling of atdgen annotations not supported by atdml: `<ocaml module="...">` on type definitions and `<ocaml name="...">` on record fields emit a warning and are otherwise ignored - `~field: user_type` with no OCaml default: warns and treats the field as required in JSON (no `create_` function generated for that type) - Record creation functions are named `create_foo` (not `make_foo`), matching atdgen's convention - Stdin mode: reads ATD from stdin, writes a copy-pasteable `module type Types = sig ... end / module Types : Types = struct ... end` snippet to stdout - Each generated type gets a submodule (`module Foo`) bundling the type and its conversion functions
Contributor
Author
|
I'm trying to figure out why the new generated file Solution: added |
Contributor
|
esgg.20190322 with `atd.4.0.0 |
Contributor
Author
|
I fixed the version constraint for esgg. The errors that remain seem independent of this release. |
Member
|
Some CI machines are stuck, but it is independent of the PR. The rest looks good, thanks |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Project page: https://github.com/ahrefs/atd
CHANGES:
Build: Dune >= 3.18 (April 2025) is now required to build the ATD tools
from source. (Require dune >= 3.18 (April 2025) ahrefs/atd#445)
atdcat: read from stdin when no input file is given, like
cat.ATD: Experimental. Module support via new
from ... import ...syntax.Types to be used must be listed explicitly; the full syntax is:
Key properties:
(e.g.
from mylib import date, status).TypeScript (atdts)
from mylib import 'a list_ne.importing file.
from foo as f import t.<python name="...">for atdpy,<ts name="...">for atdts,<ocaml name="...">for atdml.with
_(e.g. aliasclass→class_in generated code).importdeclarations are now mapped topath-separator form in the generated TypeScript import path.
For example,
import long.module.pathgeneratesimport * as path from "./long/module/path"rather than"./path".referenced in any type expression.
Examples:
atdml: Experimental. New tool. Generates a single self-contained OCaml module (
.ml+.mli) from a single.atdfile, with JSON support viaYojson.Safe.t.No separate runtime library is required; the runtime helpers are inlined
into each generated
.ml. Atdml is the recommended successor to atdgenfor OCaml JSON support.
Supported features:
unit,bool,int,float,stringabstracttype, represented asYojson.Safe.t'a list,'a option,'a nullable('a * 'b * ...)?foo),and with-default fields (
~foo) with implicit or explicit defaults(
<ocaml default="...">)<ocaml field_prefix="pre_">on record types: prepends the given prefixto all OCaml record field names while keeping the labeled arguments of
create_unprefixed (e.g.create_point ~x ~y () : point). JSON fieldnames are unaffected.
(
<ocaml repr="poly">)andis used only when strictly necessary)wrapconstruct with<ocaml module="M">or explicit<ocaml t="..." wrap="..." unwrap="..."><json adapter.ocaml="M">(module providingnormalizeand
restore) or<json adapter.to_ocaml="..." adapter.from_ocaml="...">(inline expressions); supported on sum types and records
<json name="...">to override JSON field or constructor names<ocaml name="...">to rename variant constructors in OCaml<ocaml attr="...">to attach ppx attributes (e.g.[@@deriving show])to generated type definitions
<ocaml private>on any type definition forcesprivatein the generated.mli;<ocaml public>on a primitive alias suppresses the defaultprivate, making the alias transparent to callersunit,bool,int,float,string) are generated asprivatein the.mli, preventingdirect construction outside the module. A constructor function
create_email : string -> emailis generated (also exposed asval createin submoduleEmail). Coerce back with:>(e.g.
(x :> string)).<doc text="...">documentation annotations, translated into ocamldoc(** ... *)comments in the generated code; supported on type definitions,record fields, variant constructors, and module-level head annotations
or with the
foo_of_yojson/yojson_of_foonaming schemewith OCaml keywords (e.g.
end→end_)(string * 'a) list <json repr="object">: encode association lists asJSON objects
{"key": value, ...}rather than arrays<ocaml module="...">on type definitions and<ocaml name="...">onrecord fields emit a warning and are otherwise ignored
~field: user_typewith no OCaml default: warns and treats the field asrequired in JSON (no
create_function generated for that type)create_foo(notmake_foo),matching atdgen's convention
module type Types = sig ... end / module Types : Types = struct ... endsnippet to stdout
module Foo) bundling the typeand its conversion functions