Skip to content

Commit f69f365

Browse files
authored
Merge pull request #22668 from github/tausbn/yeast-remove-support-for-fresh-literals
yeast: Remove support for fresh literals
2 parents 43c6106 + e05355a commit f69f365

7 files changed

Lines changed: 43 additions & 206 deletions

File tree

‎shared/yeast-macros/src/lib.rs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ pub fn query(input: TokenStream) -> TokenStream {
4040
/// ```text
4141
/// (kind "literal") - leaf with static content
4242
/// (kind #{expr}) - leaf with computed content (expr.to_string())
43-
/// (kind $fresh) - leaf with auto-generated unique name
4443
/// {expr} - embed a Rust expression, dispatched via
4544
/// the `IntoFieldIds` trait: `Id` pushes a
4645
/// single id; iterables (`Vec<Id>`,

‎shared/yeast-macros/src/parse.rs‎

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ fn parse_direct_node(
422422
}
423423

424424
/// Parse the inside of a parenthesized node: `kind fields... children...`
425-
/// or `kind "literal"` or `kind $fresh`.
425+
/// or `kind "literal"`.
426426
fn parse_direct_node_inner(
427427
tokens: &mut Tokens,
428428
ctx: &Ident,
@@ -474,14 +474,6 @@ fn parse_direct_node_inner(
474474
});
475475
}
476476

477-
// Check for (kind $fresh)
478-
if peek_is_dollar(tokens) {
479-
tokens.next();
480-
let name = expect_ident(tokens, "expected fresh variable name after $")?;
481-
let name_str = name.to_string();
482-
return Ok(quote! { #ctx.fresh(#kind_str, #name_str) });
483-
}
484-
485477
// Parse named fields
486478
let mut stmts = Vec::new();
487479
let mut field_args = Vec::new();
@@ -973,7 +965,7 @@ pub fn parse_rule_top(input: TokenStream) -> Result<TokenStream> {
973965
let #ctx_ident = __user_ctx;
974966
Ok(#guard)
975967
}),
976-
Box::new(|__ast: &mut yeast::Ast, mut __captures: yeast::captures::Captures, __fresh: &yeast::tree_builder::FreshScope, __source_range: Option<yeast::Range>, __user_ctx: &mut _, __translator: yeast::TranslatorHandle<'_, _>| {
968+
Box::new(|__ast: &mut yeast::Ast, mut __captures: yeast::captures::Captures, __source_range: Option<yeast::Range>, __user_ctx: &mut _, __translator: yeast::TranslatorHandle<'_, _>| {
977969
// Auto-translation prefix: recursively translate every
978970
// captured node before invoking the user's transform body,
979971
// except for `@@name` captures listed in `__skip` which the
@@ -985,7 +977,7 @@ pub fn parse_rule_top(input: TokenStream) -> Result<TokenStream> {
985977
__translator.auto_translate_captures(&mut __captures, __ast, __user_ctx, __skip)?;
986978
#(#raw_bindings)*
987979
#(#translated_bindings)*
988-
let mut #ctx_ident = yeast::build::BuildCtx::with_translator(__ast, &__captures, __fresh, __source_range, __user_ctx, __translator);
980+
let mut #ctx_ident = yeast::build::BuildCtx::with_translator(__ast, &__captures, __source_range, __user_ctx, __translator);
989981
let __result: Vec<yeast::Id> = { #transform_body };
990982
let __result = #ctx_ident.finish_rule(__result);
991983
Ok(__result)
@@ -1048,10 +1040,6 @@ fn peek_is_literal(tokens: &mut Tokens) -> bool {
10481040
matches!(tokens.peek(), Some(TokenTree::Literal(_)))
10491041
}
10501042

1051-
fn peek_is_dollar(tokens: &mut Tokens) -> bool {
1052-
matches!(tokens.peek(), Some(TokenTree::Punct(p)) if p.as_char() == '$')
1053-
}
1054-
10551043
fn peek_is_hash(tokens: &mut Tokens) -> bool {
10561044
matches!(tokens.peek(), Some(TokenTree::Punct(p)) if p.as_char() == '#')
10571045
}

‎shared/yeast/doc/yeast.md‎

Lines changed: 2 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ yeast::rule!(
184184
);
185185

186186
// Standalone — explicit context
187-
let fresh = yeast::tree_builder::FreshScope::new();
188-
let mut ctx = BuildCtx::new(ast, &captures, &fresh);
187+
let mut user_ctx = ();
188+
let mut ctx = BuildCtx::new(ast, &captures, &mut user_ctx);
189189
let id = yeast::tree!(ctx,
190190
(assignment
191191
left: {ctx.capture("lhs")}
@@ -374,25 +374,6 @@ Outside a `?`, interpolating an `Option` with `#{expr}` remains a compile error.
374374
That is deliberate: it keeps the choice between "leave the field unset" and
375375
"unwrap it" explicit at every interpolation.
376376

377-
### Fresh identifiers
378-
379-
`(kind $name)` creates a leaf node with an auto-generated unique name. All
380-
occurrences of the same `$name` within one `BuildCtx` share the same value:
381-
382-
```rust
383-
(block
384-
parameters: (block_parameters
385-
(identifier $tmp) // generates e.g. "$tmp-0"
386-
)
387-
body: (block_body
388-
(assignment
389-
left: {pat}
390-
right: (identifier $tmp) // same "$tmp-0" value
391-
)
392-
)
393-
)
394-
```
395-
396377
### Embedded Rust expressions
397378

398379
`{expr}` embeds a Rust expression whose value is appended to the
@@ -479,43 +460,6 @@ Mix `@` and `@@` freely in the same rule. In a Repeating phase both
479460
markers are equivalent (auto-translation is a no-op for repeating
480461
rules).
481462

482-
## Complete example: for-loop desugaring
483-
484-
This rule rewrites Ruby's `for pat in val do body end` into
485-
`val.each { |tmp| pat = tmp; body }`:
486-
487-
```rust
488-
let for_rule = yeast::rule!(
489-
(for
490-
pattern: (_) @pat
491-
value: (in (_) @val)
492-
body: (do (_)* @body)
493-
)
494-
=>
495-
(call
496-
receiver: {val}
497-
method: (identifier "each")
498-
block: (block
499-
parameters: (block_parameters
500-
(identifier $tmp)
501-
)
502-
body: (block_body
503-
(assignment
504-
left: {pat}
505-
right: (identifier $tmp)
506-
)
507-
{..body}
508-
)
509-
)
510-
)
511-
);
512-
```
513-
514-
Captures from the query (`@pat`, `@val`, `@body`) become Rust variables
515-
automatically: single captures bind as `Id`, repeated captures (after
516-
`*` or `+`) as `Vec<Id>`, and optional captures (after `?`) as
517-
`Option<Id>`.
518-
519463
## The `rule!` macro
520464

521465
`rule!` combines a query and a transform into a single declaration.

‎shared/yeast/src/build.rs‎

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
use std::collections::{BTreeMap, BTreeSet};
22

33
use crate::captures::Captures;
4-
use crate::tree_builder::FreshScope;
54
use crate::{Ast, FieldId, Id, KindId, NodeContent, Range, TranslatorHandle};
65

76
/// Context for building new AST nodes during a transformation.
87
///
98
/// Used by the `tree!` and `trees!` macros. Holds a mutable reference to the
10-
/// AST, a reference to the captures from a query match, a `FreshScope` for
11-
/// generating unique identifiers, and a mutable reference to a user-defined
12-
/// context of type `C`.
9+
/// AST, a reference to the captures from a query match, and a mutable reference
10+
/// to a user-defined context of type `C`.
1311
///
1412
/// The user context `C` is shared across rules via the framework's driver:
1513
/// outer rules can write to it before recursive translation, and inner rules
@@ -32,7 +30,6 @@ use crate::{Ast, FieldId, Id, KindId, NodeContent, Range, TranslatorHandle};
3230
pub struct BuildCtx<'a, C: 'a = ()> {
3331
pub ast: &'a mut Ast,
3432
pub captures: &'a Captures,
35-
pub fresh: &'a FreshScope,
3633
/// Source range of the node matched by the current rule.
3734
///
3835
/// The `rule!` macro applies this range to locally-created result roots
@@ -54,16 +51,10 @@ pub struct BuildCtx<'a, C: 'a = ()> {
5451
}
5552

5653
impl<'a, C> BuildCtx<'a, C> {
57-
pub fn new(
58-
ast: &'a mut Ast,
59-
captures: &'a Captures,
60-
fresh: &'a FreshScope,
61-
user_ctx: &'a mut C,
62-
) -> Self {
54+
pub fn new(ast: &'a mut Ast, captures: &'a Captures, user_ctx: &'a mut C) -> Self {
6355
Self {
6456
ast,
6557
captures,
66-
fresh,
6758
source_range: None,
6859
user_ctx,
6960
translator: None,
@@ -75,14 +66,12 @@ impl<'a, C> BuildCtx<'a, C> {
7566
pub fn with_source_range(
7667
ast: &'a mut Ast,
7768
captures: &'a Captures,
78-
fresh: &'a FreshScope,
7969
source_range: Option<Range>,
8070
user_ctx: &'a mut C,
8171
) -> Self {
8272
Self {
8373
ast,
8474
captures,
85-
fresh,
8675
source_range,
8776
user_ctx,
8877
translator: None,
@@ -95,15 +84,13 @@ impl<'a, C> BuildCtx<'a, C> {
9584
pub fn with_translator(
9685
ast: &'a mut Ast,
9786
captures: &'a Captures,
98-
fresh: &'a FreshScope,
9987
source_range: Option<Range>,
10088
user_ctx: &'a mut C,
10189
translator: TranslatorHandle<'a, C>,
10290
) -> Self {
10391
Self {
10492
ast,
10593
captures,
106-
fresh,
10794
source_range,
10895
user_ctx,
10996
translator: Some(translator),
@@ -262,12 +249,6 @@ impl<'a, C> BuildCtx<'a, C> {
262249
let source_range = self.source_range_of(source).map(Range::empty_at_start);
263250
self.literal_with_source_range(kind, value, source_range)
264251
}
265-
266-
/// Create a leaf node with an auto-generated unique name.
267-
pub fn fresh(&mut self, kind: &'static str, name: &str) -> Id {
268-
let generated = self.fresh.resolve(name);
269-
self.create_named_token_with_range(kind, generated, None)
270-
}
271252
}
272253

273254
impl<C: Clone> BuildCtx<'_, C> {
@@ -302,7 +283,7 @@ impl<C: Clone> BuildCtx<'_, C> {
302283

303284
/// Run `f` with a temporary child [`BuildCtx`] whose `user_ctx` is
304285
/// a fresh clone of the current one, sharing everything else
305-
/// (`ast`, `captures`, `fresh`, source ranges, `translator`) by re-borrow.
286+
/// (`ast`, `captures`, source ranges, `translator`) by re-borrow.
306287
/// Nodes constructed through the child remain part of the current rule
307288
/// invocation. Any mutations `f` makes to the child's `user_ctx`
308289
/// are discarded when it returns — no restore needed, because the
@@ -334,7 +315,6 @@ impl<C: Clone> BuildCtx<'_, C> {
334315
let mut child = BuildCtx {
335316
ast: &mut *self.ast,
336317
captures: self.captures,
337-
fresh: self.fresh,
338318
source_range: self.source_range,
339319
user_ctx: &mut child_user_ctx,
340320
translator: self.translator,

0 commit comments

Comments
 (0)