Skip to content

Commit 42b1900

Browse files
committed
spec
1 parent 8809dbf commit 42b1900

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

tools/src/migrate.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Migration Framework – Current Capabilities
2+
3+
This document captures what the migration framework currently supports, based on `tools/src/migrate.ml` (and helpers in `tools/src/transforms.ml`, `compiler/ml/builtin_attributes.ml`, and `analysis/src/Cmt.ml`).
4+
5+
## Inputs & Preconditions
6+
7+
- Targets: `*.res` and `*.resi` files.
8+
- Requires build artifacts for the file’s module (CMT/CMTI). If not found, migration aborts with an error message asking to build the project.
9+
- Output modes: write back to file or print to stdout.
10+
11+
## Deprecation Sources
12+
13+
- Migration data is harvested from `@deprecated({ reason, migrate, migrateInPipeChain })` attributes recorded in CMT extras.
14+
- Captured context where deprecation was used:
15+
- `FunctionCall` – a function call site
16+
- `Reference` – a value/identifier reference (non‑call)
17+
18+
## Supported Rewrites
19+
20+
- Direct function calls (non‑pipe):
21+
- If `migrate` is an application expression, the call is rewritten according to the template (see Templates & Placeholders).
22+
- Pipe calls using `->`:
23+
- If `migrateInPipeChain` is provided, it is used for piped form. Special handling for single‑step chains (see Pipe Semantics).
24+
- Identifier references (non‑call):
25+
- If `migrate` is provided, the reference is replaced by that expression.
26+
- Special case: if the template is `f()` (unit call), treat it as `f` to avoid adding a spurious unit application.
27+
- Type constructor references:
28+
- If `migrate` is `%replace.type(: <core_type>)`, type constructor occurrences within the deprecation’s location range are replaced by `<core_type>`.
29+
- If the template is a constructor with its own type arguments, original type arguments are appended; otherwise original arguments are dropped.
30+
- Extension rename:
31+
- Extension `todo_` is remapped to `todo`.
32+
33+
## Templates & Placeholders
34+
35+
- Template form: application expressions only for call‑site rewrites; arbitrary expressions for reference rewrites.
36+
- Placeholders inside template expressions:
37+
- `%insert.unlabelledArgument(<int>)`
38+
- 0‑based index into the source call’s unlabelled arguments.
39+
- `%insert.labelledArgument("<name>")`
40+
- Refers to a labelled or optional source argument by name.
41+
- Placeholder replacement occurs anywhere inside the template expression, not only as direct arguments.
42+
- Consumed arguments are dropped from the original call; remaining arguments keep order.
43+
- Label renaming:
44+
- If a template argument has a label and its expression is a labelled placeholder, the corresponding source argument is emitted under the template’s label (rename).
45+
46+
## Pipe Semantics
47+
48+
- For piped calls, the pipe LHS is considered unlabelled argument index 0 for placeholder resolution.
49+
- When constructing the inner call, unlabelled drop positions are adjusted to account for the fact that the LHS does not appear as an inner argument.
50+
- Single‑step collapse:
51+
- If the LHS is not itself a pipe and `migrateInPipeChain` exists:
52+
- If `migrate` exists, prefer collapsing the step by applying `migrate` with the LHS inserted as unlabelled argument index 0.
53+
- Otherwise use `migrateInPipeChain` in piped form.
54+
- Empty‑args piped form:
55+
- If piping into a bare identifier and the chosen piped template inserts no arguments, the result remains `lhs -> newFn` (no extra parentheses).
56+
57+
## Transforms (`@apply.transforms`)
58+
59+
- Attribute name: `@apply.transforms(["<id>", ...])` on expressions.
60+
- Resolution: IDs map to functions in `tools/src/transforms.ml`. Unknown IDs are ignored.
61+
- Application:
62+
- Attributes attached to template or placeholder expressions are preserved on replacements and applied in a second pass over `.res` implementations.
63+
- Currently implemented transform: `dropUnitArgumentsInApply` (drops only unlabelled unit arguments from application nodes).
64+
- Other registry entries are stubs and currently no‑ops.
65+
- Note: The second pass runs for `.res` (implementations). Interfaces (`.resi`) do not contain expression bodies; transform pass is not applied there.
66+
67+
## Limitations / Not Supported (Today)
68+
69+
- Call‑site rewrite requires the template to be an application expression; non‑application templates for calls are ignored.
70+
- Placeholders with negative indices are ignored (no replacement, no drop).
71+
- No special handling for method sends beyond normal call/pipe matching.
72+
- Transforms run only in `.res`. Attachments in `.resi` will be carried in attrs but not executed.
73+
- Only type constructor occurrences are replaced via `%replace.type`; no pattern matching over other type forms.
74+
- Transform registry is minimal; most listed transforms are placeholders.
75+
76+
## Summary of Behavior
77+
78+
1. Collect deprecated uses from CMT (with optional templates and contexts).
79+
2. Rewrite references/calls/pipes according to provided templates and placeholder rules.
80+
3. Adjust labels, drop consumed args, and append inserted template args.
81+
4. For `.res`, run a second pass applying any `@apply.transforms` attributes that were attached to expressions during rewriting.
82+
5. Print updated AST; write file or stdout.

0 commit comments

Comments
 (0)