Walker: node-attached HintMode via Node::Hinted (ADR-0024 §HintMode-per-node)

Replaces the hint resolver's signature-matching (does the expected set
contain all five literal forms? an Ident{NewName}?) with a grammar-
declared annotation. New Node::Hinted { mode, inner } wrapper; the
walker records the mode in WalkContext::pending_hint_mode on entry and
clears it on any successful match (cursor moved past the slot — this
also undoes the leak where a failed Hinted branch of a Choice would
otherwise strand a stale mode). The resolver reads pending_hint_mode
directly.

Value-literal fallback slots carry ProseOnly; NewName ident slots carry
ForceProse. hint_mode_at_input_inner now delegates to
hint_resolution_at_input — one resolution path, no duplicated logic.
No behaviour change; the typing-surface matrix guards it.
This commit is contained in:
claude@clouddev1
2026-05-15 21:58:22 +00:00
parent f1ff5970bf
commit 911a537a83
8 changed files with 193 additions and 165 deletions
+32
View File
@@ -84,6 +84,28 @@ pub fn walk_node(
per_byte: &mut Vec<ByteClass>,
) -> NodeWalkResult {
let pos = skip_whitespace(source, position);
let result = walk_node_inner(source, pos, node, ctx, path, per_byte);
// ADR-0024 §HintMode-per-node: `pending_hint_mode` records
// the Hinted slot the cursor is currently inside. Any
// successful match means the cursor advanced past whatever
// slot was pending — clear it. This also undoes the leak
// where a failed `Hinted` branch of a `Choice` sets the
// mode and the `Choice` then matches via a different
// branch: that branch's match clears the stale mode.
if matches!(result, NodeWalkResult::Matched { .. }) {
ctx.pending_hint_mode = None;
}
result
}
fn walk_node_inner(
source: &str,
pos: usize,
node: &Node,
ctx: &mut WalkContext,
path: &mut MatchedPath,
per_byte: &mut Vec<ByteClass>,
) -> NodeWalkResult {
match node {
Node::Word(word) => walk_word(source, pos, word, path, per_byte),
Node::Punct(ch) => walk_punct(source, pos, *ch, path, per_byte),
@@ -156,6 +178,16 @@ pub fn walk_node(
}
result
}
Node::Hinted { mode, inner } => {
// ADR-0024 §HintMode-per-node. Record the grammar's
// declared hint mode so the hint resolver can read
// it directly. The `walk_node` wrapper clears it on
// any successful match (the cursor moved past the
// slot), so a Hinted slot whose inner fails at EOF
// leaves the mode set for the resolver to read.
ctx.pending_hint_mode = Some(*mode);
walk_node(source, pos, inner, ctx, path, per_byte)
}
Node::Flag(name) => walk_flag(source, pos, name, path, per_byte),
Node::Repeated {
inner,