Skip to content

Commit 124c112

Browse files
mjambonclaude
andcommitted
Add feature support matrix to documentation
Adds internal/src/main.ml, a small OCaml program that encodes which ATD features each backend supports (Yes/Planned/No) and generates an RST page. Run `make` in internal/ to regenerate doc/support-matrix.rst. The matrix is included in the ATD Project page in the Sphinx docs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 923ae0f commit 124c112

File tree

5 files changed

+391
-0
lines changed

5 files changed

+391
-0
lines changed

doc/atd-project.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ Some properties of interest of ATD schemas include:
2121
* support for sum types aka algebraic data types or tagged unions
2222
* options to select alternate representations than the default, e.g.
2323
use a JSON object rather than an array of pairs
24+
25+
.. include:: support-matrix.rst

doc/support-matrix.rst

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
Feature Support Matrix
2+
======================
3+
4+
For each ATD feature, target languages are grouped by support level.
5+
6+
Basic types
7+
~~~~~~~~~~~
8+
9+
unit, bool, int, float, string
10+
11+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
12+
13+
Abstract type
14+
~~~~~~~~~~~~~
15+
16+
Any JSON value (abstract keyword)
17+
18+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
19+
20+
List / array
21+
~~~~~~~~~~~~
22+
23+
The list type constructor
24+
25+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
26+
27+
Option type
28+
~~~~~~~~~~~
29+
30+
ATD-style "None" / ["Some", x] encoding
31+
32+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
33+
34+
Nullable
35+
~~~~~~~~
36+
37+
JSON null <-> None, other value <-> Some x
38+
39+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
40+
41+
Wrap type
42+
~~~~~~~~~
43+
44+
Custom type wrappers ('a wrap)
45+
46+
**Supported:** atdml (OCaml), atdgen (OCaml), atdts (TypeScript), atdd (Dart), atdcpp (C++)
47+
48+
**Not yet:** atdpy (Python), atdj (Java), atds (Scala)
49+
50+
Records
51+
~~~~~~~
52+
53+
Record types with named fields
54+
55+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
56+
57+
Sum types
58+
~~~~~~~~~
59+
60+
Tagged unions / variants
61+
62+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
63+
64+
Tuples
65+
~~~~~~
66+
67+
Fixed-arity product types
68+
69+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
70+
71+
Parametric types
72+
~~~~~~~~~~~~~~~~
73+
74+
Generic / parameterized type definitions
75+
76+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
77+
78+
Type aliases
79+
~~~~~~~~~~~~
80+
81+
Simple aliases (type t = int list)
82+
83+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
84+
85+
Optional fields
86+
~~~~~~~~~~~~~~~
87+
88+
?field — absent JSON key <-> None
89+
90+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
91+
92+
Default-value fields
93+
~~~~~~~~~~~~~~~~~~~~
94+
95+
~field — absent JSON key uses a default
96+
97+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
98+
99+
Doc comments
100+
~~~~~~~~~~~~
101+
102+
<doc text="..."> -> language docstrings
103+
104+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala)
105+
106+
**Not yet:** atdd (Dart), atdcpp (C++)
107+
108+
JSON field names
109+
~~~~~~~~~~~~~~~~
110+
111+
<json name="..."> on record fields
112+
113+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
114+
115+
JSON variant names
116+
~~~~~~~~~~~~~~~~~~
117+
118+
<json name="..."> on sum type constructors
119+
120+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
121+
122+
Assoc as JSON object
123+
~~~~~~~~~~~~~~~~~~~~
124+
125+
(string * v) list <json repr="object">
126+
127+
**Supported:** atdml (OCaml), atdgen (OCaml), atdpy (Python), atdts (TypeScript)
128+
129+
**Not yet:** atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
130+
131+
JSON adapter
132+
~~~~~~~~~~~~
133+
134+
Custom pre/post-processing hooks
135+
136+
**Supported:** atdml (OCaml), atdgen (OCaml)
137+
138+
**Not yet:** atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
139+
140+
Cross-file imports
141+
~~~~~~~~~~~~~~~~~~
142+
143+
from module import type1, type2
144+
145+
**Supported:** atdml (OCaml), atdpy (Python), atdts (TypeScript)
146+
147+
**Not yet:** atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
148+
149+
**Not supported:** atdgen (OCaml)
150+
151+
Shared/cyclic types
152+
~~~~~~~~~~~~~~~~~~~
153+
154+
The shared type constructor for graphs
155+
156+
**Supported:** atdgen (OCaml)
157+
158+
**Not yet:** atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
159+
160+
**Not supported:** atdml (OCaml), atdpy (Python), atdts (TypeScript)
161+
162+
Open enumerations
163+
~~~~~~~~~~~~~~~~~
164+
165+
Unknown variants round-tripped as-is
166+
167+
**Supported:** atdgen (OCaml)
168+
169+
**Not yet:** atdpy (Python), atdts (TypeScript), atdj (Java), atds (Scala), atdd (Dart), atdcpp (C++)
170+
171+
**Not supported:** atdml (OCaml)
172+

internal/Makefile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Feature Support Matrix Generator
2+
# ==================================
3+
#
4+
# This directory contains a small OCaml program (src/main.ml) that generates
5+
# the feature support matrix page for the ATD documentation
6+
# (../doc/support-matrix.rst).
7+
#
8+
# Editing the table
9+
# -----------------
10+
# All data lives in src/main.ml as typed OCaml values (yes/no/planned per
11+
# feature per backend). This makes it easy to update individual cells, add
12+
# rows or columns, and keep the RST output consistently formatted — much
13+
# easier than editing a wide hand-crafted RST table directly.
14+
#
15+
# Regenerating the RST file
16+
# -------------------------
17+
# make build the program and overwrite ../doc/support-matrix.rst
18+
# make build build only, do not overwrite the RST file
19+
#
20+
# The generated file is committed to the repository so that the documentation
21+
# can be built without running OCaml.
22+
23+
DUNE := dune
24+
ROOT := ..
25+
OUT := $(ROOT)/doc/support-matrix.rst
26+
27+
.PHONY: all build
28+
29+
all: build
30+
cd $(ROOT) && $(DUNE) exec internal/src/main.exe > doc/support-matrix.rst
31+
32+
build:
33+
cd $(ROOT) && $(DUNE) build internal/src/main.exe

internal/src/dune

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
(executable
2+
(name main))

internal/src/main.ml

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
(* Support level for one feature in one target language. *)
2+
type support =
3+
| Yes (* supported *)
4+
| Planned (* not yet, but could/should be *)
5+
| No (* not supported and not planned *)
6+
7+
(* All features for one target language. Adding a new language means adding
8+
a new entry to the [languages] list below, starting from [all_yes] and
9+
overriding the features that are not fully supported. *)
10+
type lang_support = {
11+
basic_types: support;
12+
abstract: support;
13+
list_: support;
14+
option_: support;
15+
nullable: support;
16+
wrap: support;
17+
records: support;
18+
sum_types: support;
19+
tuples: support;
20+
parametric: support;
21+
aliases: support;
22+
optional_fields: support;
23+
default_fields: support;
24+
doc_comments: support;
25+
json_field_names: support;
26+
json_variant_names: support;
27+
json_repr_object: support;
28+
json_adapter: support;
29+
imports: support;
30+
shared: support;
31+
open_enums: support;
32+
}
33+
34+
(* A feature has a display name, a short description, and an accessor into
35+
[lang_support]. The accessor is what lets the printer iterate over features
36+
without a big match expression per language. *)
37+
type feature = {
38+
name: string;
39+
description: string;
40+
get: lang_support -> support;
41+
}
42+
43+
(* Row order in the output. Adding a new feature means adding a field to
44+
[lang_support], a [features] entry here, and updating each language
45+
below. *)
46+
let features : feature list = [
47+
{ name = "Basic types"; description = "unit, bool, int, float, string"; get = fun s -> s.basic_types };
48+
{ name = "Abstract type"; description = "Any JSON value (abstract keyword)"; get = fun s -> s.abstract };
49+
{ name = "List / array"; description = "The list type constructor"; get = fun s -> s.list_ };
50+
{ name = "Option type"; description = "ATD-style \"None\" / [\"Some\", x] encoding"; get = fun s -> s.option_ };
51+
{ name = "Nullable"; description = "JSON null <-> None, other value <-> Some x"; get = fun s -> s.nullable };
52+
{ name = "Wrap type"; description = "Custom type wrappers ('a wrap)"; get = fun s -> s.wrap };
53+
{ name = "Records"; description = "Record types with named fields"; get = fun s -> s.records };
54+
{ name = "Sum types"; description = "Tagged unions / variants"; get = fun s -> s.sum_types };
55+
{ name = "Tuples"; description = "Fixed-arity product types"; get = fun s -> s.tuples };
56+
{ name = "Parametric types"; description = "Generic / parameterized type definitions"; get = fun s -> s.parametric };
57+
{ name = "Type aliases"; description = "Simple aliases (type t = int list)"; get = fun s -> s.aliases };
58+
{ name = "Optional fields"; description = "?field — absent JSON key <-> None"; get = fun s -> s.optional_fields };
59+
{ name = "Default-value fields"; description = "~field — absent JSON key uses a default"; get = fun s -> s.default_fields };
60+
{ name = "Doc comments"; description = "<doc text=\"...\"> -> language docstrings"; get = fun s -> s.doc_comments };
61+
{ name = "JSON field names"; description = "<json name=\"...\"> on record fields"; get = fun s -> s.json_field_names };
62+
{ name = "JSON variant names"; description = "<json name=\"...\"> on sum type constructors"; get = fun s -> s.json_variant_names };
63+
{ name = "Assoc as JSON object"; description = "(string * v) list <json repr=\"object\">"; get = fun s -> s.json_repr_object };
64+
{ name = "JSON adapter"; description = "Custom pre/post-processing hooks"; get = fun s -> s.json_adapter };
65+
{ name = "Cross-file imports"; description = "from module import type1, type2"; get = fun s -> s.imports };
66+
{ name = "Shared/cyclic types"; description = "The shared type constructor for graphs"; get = fun s -> s.shared };
67+
{ name = "Open enumerations"; description = "Unknown variants round-tripped as-is"; get = fun s -> s.open_enums };
68+
]
69+
70+
(* Baseline: every feature supported. Each language starts from this and
71+
overrides only the exceptions. *)
72+
let all_yes = {
73+
basic_types = Yes;
74+
abstract = Yes;
75+
list_ = Yes;
76+
option_ = Yes;
77+
nullable = Yes;
78+
wrap = Yes;
79+
records = Yes;
80+
sum_types = Yes;
81+
tuples = Yes;
82+
parametric = Yes;
83+
aliases = Yes;
84+
optional_fields = Yes;
85+
default_fields = Yes;
86+
doc_comments = Yes;
87+
json_field_names = Yes;
88+
json_variant_names = Yes;
89+
json_repr_object = Yes;
90+
json_adapter = Yes;
91+
imports = Yes;
92+
shared = Yes;
93+
open_enums = Yes;
94+
}
95+
96+
(* The data. Each entry is (display name, support record). Column order in
97+
the output matches the order here. *)
98+
let languages : (string * lang_support) list = [
99+
"atdml (OCaml)", { all_yes with
100+
shared = No;
101+
open_enums = No;
102+
};
103+
"atdgen (OCaml)", { all_yes with
104+
imports = No;
105+
};
106+
"atdpy (Python)", { all_yes with
107+
wrap = Planned;
108+
json_adapter = Planned;
109+
shared = No;
110+
open_enums = Planned;
111+
};
112+
"atdts (TypeScript)", { all_yes with
113+
json_adapter = Planned;
114+
shared = No;
115+
open_enums = Planned;
116+
};
117+
"atdj (Java)", { all_yes with
118+
wrap = Planned;
119+
json_repr_object = Planned;
120+
json_adapter = Planned;
121+
imports = Planned;
122+
shared = Planned;
123+
open_enums = Planned;
124+
};
125+
"atds (Scala)", { all_yes with
126+
wrap = Planned;
127+
json_repr_object = Planned;
128+
json_adapter = Planned;
129+
imports = Planned;
130+
shared = Planned;
131+
open_enums = Planned;
132+
};
133+
"atdd (Dart)", { all_yes with
134+
doc_comments = Planned;
135+
json_repr_object = Planned;
136+
json_adapter = Planned;
137+
imports = Planned;
138+
shared = Planned;
139+
open_enums = Planned;
140+
};
141+
"atdcpp (C++)", { all_yes with
142+
doc_comments = Planned;
143+
json_repr_object = Planned;
144+
json_adapter = Planned;
145+
imports = Planned;
146+
shared = Planned;
147+
open_enums = Planned;
148+
};
149+
]
150+
151+
let label_of = function
152+
| Yes -> "Supported"
153+
| Planned -> "Not yet"
154+
| No -> "Not supported"
155+
156+
(* Output: reStructuredText (RST) consumed by Sphinx to produce the
157+
doc/support-matrix page included in the ATD documentation.
158+
Each feature becomes an RST subsection (~~ underline). Under each
159+
subsection, languages are grouped by support level, with empty groups
160+
omitted, producing lines of the form:
161+
**Supported:** atdml (OCaml), atdgen (OCaml), ...
162+
Run `make` in this directory to regenerate doc/support-matrix.rst. *)
163+
let () =
164+
print_string "Feature Support Matrix\n";
165+
print_string "======================\n";
166+
print_char '\n';
167+
print_string "For each ATD feature, target languages are grouped by support level.\n";
168+
print_char '\n';
169+
List.iter (fun feat ->
170+
let n = String.length feat.name in
171+
Printf.printf "%s\n%s\n\n" feat.name (String.make n '~');
172+
Printf.printf "%s\n\n" feat.description;
173+
List.iter (fun level ->
174+
let langs =
175+
List.filter_map
176+
(fun (lang, ls) -> if feat.get ls = level then Some lang else None)
177+
languages
178+
in
179+
if langs <> [] then
180+
Printf.printf "**%s:** %s\n\n" (label_of level) (String.concat ", " langs)
181+
) [Yes; Planned; No]
182+
) features

0 commit comments

Comments
 (0)