Patching
Semantic patch streams over Draxl node ids, slots, anchors, and scalar paths.
Draxl patch streams are executable semantic edit instructions over the Draxl AST. A patch stream names stable node ids, schema-defined slots, attachment relations, and scalar paths.
This makes the patch surface suitable for agents, replay, review, and merge analysis.
Patch Stream Shape
// Rename the public entrypoint before changing call sites.
set @f1.name = add_one_fast
insert @f1.body[ah]: @s4 @e4 trace();
replace @e3: @e5 zWhole-line // comments are patch notes. They are ignored by patch parsing and
execution.
Addressing
Node refs name existing nodes:
@f1
@s4
@e3Slot refs name profile-defined child slots:
file.items
@m1.items
@f1.params
@f1.body
@f1.ret
@let1.init
@e7.armsPaths name scalar fields:
@f1.name
@d1.text
@e7.op
@s2.semiOperators
| Operator | Purpose |
|---|---|
insert | Add a new node into a ranked slot. |
put | Set the occupant of a single-child slot. |
replace | Rewrite a node body while preserving its outer identity. |
delete | Remove a removable node. |
move | Relocate a node to another legal destination. |
attach | Attach a doc or comment node to a sibling. |
detach | Remove explicit attachment from a doc or comment node. |
set | Update a scalar field. |
clear | Clear a clearable scalar field. |
Canonical syntax:
insert @f1.body[ah]: @s4 @e4 trace();
put @f1.ret: @t9 i128
replace @e2: (@e2 x * @l2 2)
delete @s4
move @s4 -> @f1.body[ai]
attach @d2 -> @f1
detach @d2
set @f1.name = add_one_fast
clear @d1.textFragment Rules
Fragments use ordinary Draxl source.
insertfragments include the new outer node id and omit the outer rank.putfragments include the new outer node id and omit slot metadata.replacefragments rewrite the target body and preserve the target id.- multi-line fragments are allowed when delimiters stay balanced.
For example, this operation preserves @e2 as the edited expression identity:
replace @e2: (@e2 x * @l2 2)This operation creates a new statement @s4 at rank ah in @f1.body:
insert @f1.body[ah]: @s4 @e4 trace();CLI Workflow
Create a patch stream:
cat > /tmp/change.dxpatch <<'PATCH'
// Rename the function and insert a trace statement.
set @f1.name = add_one_fast
insert @f1.body[ah]: @s4 @e4 trace();
PATCHPreview the result:
cargo run -p draxl-cli -- patch examples/01_add.rs.dx /tmp/change.dxpatchRewrite the source file:
cargo run -p draxl-cli -- patch --in-place examples/01_add.rs.dx /tmp/change.dxpatchThe executor parses the source, resolves patch targets against the current tree, applies the operations, validates the result, and prints canonical Draxl source.
Current Scope
The current Rust profile supports:
insertinto rankeditems,fields,variants,params,body, andarmsslotsputinto modeled single-child slots such asret,ty,pat,init,expr,lhs,rhs,callee,scrutinee,guard, and armbodyreplacefor items, fields, variants, parameters, statements, match arms, expressions, types, patterns, docs, and commentsdeleteandmovefor removable nodesattachanddetachfor doc and comment nodessetandclearover names, trivia text, operators, and statement semicolon state
Use Merge to compare two patch streams against the same base.