21
21
22
22
use std:: cell:: Cell ;
23
23
use std:: fmt;
24
+ use std:: ops:: Deref ;
24
25
use std:: path:: PathBuf ;
25
26
use std:: ptr:: NonNull ;
26
27
27
- use self :: storage:: { FromConcrete , ToConcrete } ;
28
+ use self :: storage:: { FromConcrete , ToConcrete , Storage } ;
28
29
29
30
mod generation {
30
31
use std:: cell:: Cell ;
@@ -233,14 +234,39 @@ mod storage {
233
234
}
234
235
}
235
236
237
+ /// Thread-local reference, to be used in place of `&'static T`
238
+ /// when it shouldn't be allowed to escape the thread.
239
+ #[ repr( C ) ]
240
+ #[ derive( Copy , Clone ) ]
241
+ pub struct ThreadRef < T : ?Sized + ' static > ( & ' static T ) ;
242
+
243
+ impl < T : ?Sized + ' static > !Send for ThreadRef < T > { }
244
+ impl < T : ?Sized + ' static > !Sync for ThreadRef < T > { }
245
+
246
+ impl < T : ?Sized + ' static > Deref for ThreadRef < T > {
247
+ type Target = T ;
248
+ fn deref ( & self ) -> & T {
249
+ self . 0
250
+ }
251
+ }
252
+
253
+ impl < T : ?Sized + ' static > ThreadRef < T > {
254
+ pub fn new ( x : & ' static T ) -> Self {
255
+ ThreadRef ( x)
256
+ }
257
+ }
258
+
236
259
storage_concrete_passthrough ! {
237
260
[ ] ( ) ,
238
261
[ ] bool ,
262
+ [ ] char ,
239
263
[ ' a] & ' a str ,
264
+ [ ] ThreadRef <str >,
240
265
241
266
// FIXME(eddyb) achieve ABI compatibility for these types.
242
- [ ] :: TokenNode ,
243
267
[ ] :: Delimiter ,
268
+ [ ] :: LiteralKind ,
269
+ [ ] :: Spacing ,
244
270
[ ] :: LexError ,
245
271
[ ] :: LineColumn ,
246
272
[ ] :: Level ,
@@ -269,16 +295,11 @@ macro_rules! each_frontend_method {
269
295
$meth!( fn token_stream_is_empty( & self , stream: & Self :: TokenStream ) -> bool ; ) ;
270
296
$meth!( fn token_stream_from_str( & self , src: & str )
271
297
-> Result <Self :: TokenStream , :: LexError >; ) ;
272
- $meth!( fn token_stream_delimited( & self , span: Self :: Span ,
273
- delimiter: :: Delimiter ,
274
- delimed: Self :: TokenStream )
275
- -> Self :: TokenStream ; ) ;
276
- $meth!( fn token_stream_from_token_tree( & self , node: :: TokenNode , span: Self :: Span )
298
+ $meth!( fn token_stream_from_token_tree( & self , node: Self :: TokenNode , span: Self :: Span )
277
299
-> Self :: TokenStream ; ) ;
278
300
$meth!( fn token_stream_to_token_tree( & self , stream: Self :: TokenStream )
279
- -> ( Self :: Span ,
280
- Result <( :: TokenNode , Option <Self :: TokenStream >) ,
281
- ( :: Delimiter , Self :: TokenStream ) >) ; ) ;
301
+ -> ( ( Self :: Span , Self :: TokenNode ) ,
302
+ Option <Self :: TokenStream >) ; ) ;
282
303
$meth!( fn token_stream_trees( & self , stream: Self :: TokenStream ) -> Self :: TokenCursor ; ) ;
283
304
284
305
$meth!( fn token_stream_builder_cleanup( & self , _builder: Self :: TokenStreamBuilder ) -> ( ) { } ) ;
@@ -323,6 +344,12 @@ macro_rules! each_frontend_method {
323
344
$meth!( fn span_end( & self , span: Self :: Span ) -> :: LineColumn ; ) ;
324
345
$meth!( fn span_join( & self , first: Self :: Span , second: Self :: Span ) -> Option <Self :: Span >; ) ;
325
346
$meth!( fn span_resolved_at( & self , span: Self :: Span , at: Self :: Span ) -> Self :: Span ; ) ;
347
+
348
+ $meth!( fn term_debug( & self , term: Self :: Term , f: & mut fmt:: Formatter ) -> fmt:: Result {
349
+ fmt:: Debug :: fmt( & term, f)
350
+ } ) ;
351
+ $meth!( fn term_intern( & self , string: & str ) -> Self :: Term ; ) ;
352
+ $meth!( fn term_as_str( & self , term: Self :: Term ) -> ThreadRef <str >; ) ;
326
353
}
327
354
}
328
355
@@ -337,9 +364,49 @@ pub trait FrontendInterface {
337
364
type Diagnostic : ' static ;
338
365
/// NB. has to be the same size as u32.
339
366
type Span : ' static + Copy + Eq + fmt:: Debug ;
367
+ /// NB. has to be the same size as u32.
368
+ type Term : ' static + Copy + Eq + fmt:: Debug ;
369
+ /// Only needed for object safety, should always be `TokenNode<Self>`.
370
+ type TokenNode ;
340
371
each_frontend_method ! ( define_frontend_trait_method) ;
341
372
}
342
373
374
+ macro_rules! frontend_wrapper {
375
+ ( enum $name: ident<$F: ident> { $( $variant: ident( $( $field: ident: $field_ty: ty) ,* ) ) ,* } ) => {
376
+ #[ repr( C ) ]
377
+ pub enum $name<$F: FrontendInterface > {
378
+ $( $variant( $( $field_ty) ,* ) ) ,*
379
+ }
380
+
381
+ impl <F : FrontendInterface > FromConcrete <$name<F >, $name<Frontend >> for Storage <F > {
382
+ fn from_concrete( & self , x: $name<F >) -> $name<Frontend > {
383
+ match x {
384
+ $( $name:: $variant( $( $field) ,* ) => {
385
+ $name:: $variant( $( self . from_concrete( $field) ) ,* )
386
+ } ) ,*
387
+ }
388
+ }
389
+ }
390
+
391
+ impl <F : FrontendInterface > ToConcrete <$name<Frontend >, $name<F >> for Storage <F > {
392
+ fn to_concrete( & self , x: $name<Frontend >) -> $name<F > {
393
+ match x {
394
+ $( $name:: $variant( $( $field) ,* ) => {
395
+ $name:: $variant( $( self . to_concrete( $field) ) ,* )
396
+ } ) ,*
397
+ }
398
+ }
399
+ }
400
+ }
401
+ }
402
+
403
+ frontend_wrapper ! ( enum TokenNode <F > {
404
+ Group ( delim: :: Delimiter , delimed: F :: TokenStream ) ,
405
+ Term ( term: F :: Term ) ,
406
+ Op ( op: char , spacing: :: Spacing ) ,
407
+ Literal ( kind: :: LiteralKind , contents: F :: Term , suffix: Option <F :: Term >)
408
+ } ) ;
409
+
343
410
macro_rules! define_boxed {
344
411
( $( $name: ident { cleanup: $cleanup: ident } ) ,* ) => {
345
412
$(
@@ -353,28 +420,28 @@ macro_rules! define_boxed {
353
420
Frontend . $cleanup( $name( boxed) )
354
421
}
355
422
}
356
- impl <S , T : ' static > FromConcrete <T , $name> for storage :: Storage <S >
423
+ impl <S , T : ' static > FromConcrete <T , $name> for Storage <S >
357
424
where $name: storage:: Concrete <S , Concrete = T >
358
425
{
359
426
fn from_concrete( & self , x: T ) -> $name {
360
427
$name( self . from_concrete( Box :: new( x) ) )
361
428
}
362
429
}
363
- impl <S , T : ' static > ToConcrete <$name, T > for storage :: Storage <S >
430
+ impl <S , T : ' static > ToConcrete <$name, T > for Storage <S >
364
431
where $name: storage:: Concrete <S , Concrete = T >
365
432
{
366
433
fn to_concrete( & self , x: $name) -> T {
367
434
* self . to_concrete( x. 0 )
368
435
}
369
436
}
370
- impl <' a, S , T : ' static > ToConcrete <& ' a $name, & ' a T > for storage :: Storage <S >
437
+ impl <' a, S , T : ' static > ToConcrete <& ' a $name, & ' a T > for Storage <S >
371
438
where $name: storage:: Concrete <S , Concrete = T >
372
439
{
373
440
fn to_concrete( & self , x: & ' a $name) -> & ' a T {
374
441
self . to_concrete( & x. 0 )
375
442
}
376
443
}
377
- impl <' a, S , T : ' static > ToConcrete <& ' a mut $name, & ' a mut T > for storage :: Storage <S >
444
+ impl <' a, S , T : ' static > ToConcrete <& ' a mut $name, & ' a mut T > for Storage <S >
378
445
where $name: storage:: Concrete <S , Concrete = T >
379
446
{
380
447
fn to_concrete( & self , x: & ' a mut $name) -> & ' a mut T {
@@ -442,14 +509,14 @@ macro_rules! define_inline {
442
509
impl <F : FrontendInterface > storage:: Concrete <F > for $name {
443
510
type Concrete = F :: $name;
444
511
}
445
- impl <S , T : Copy + ' static > FromConcrete <T , $name> for storage :: Storage <S >
512
+ impl <S , T : Copy + ' static > FromConcrete <T , $name> for Storage <S >
446
513
where $name: storage:: Concrete <S , Concrete = T >
447
514
{
448
515
fn from_concrete( & self , x: T ) -> $name {
449
516
$name( self . from_concrete( x) )
450
517
}
451
518
}
452
- impl <S , T : Copy + ' static > ToConcrete <$name, T > for storage :: Storage <S >
519
+ impl <S , T : Copy + ' static > ToConcrete <$name, T > for Storage <S >
453
520
where $name: storage:: Concrete <S , Concrete = T >
454
521
{
455
522
fn to_concrete( & self , x: $name) -> T {
@@ -460,14 +527,20 @@ macro_rules! define_inline {
460
527
}
461
528
}
462
529
463
- define_inline ! ( Span ) ;
530
+ define_inline ! ( Span , Term ) ;
464
531
465
532
impl fmt:: Debug for Span {
466
533
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
467
534
Frontend . span_debug ( * self , f)
468
535
}
469
536
}
470
537
538
+ impl fmt:: Debug for Term {
539
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
540
+ Frontend . term_debug ( * self , f)
541
+ }
542
+ }
543
+
471
544
pub ( crate ) struct Frontend ;
472
545
473
546
macro_rules! define_frontend_current_method {
@@ -485,6 +558,8 @@ impl FrontendInterface for Frontend {
485
558
type SourceFile = SourceFile ;
486
559
type Diagnostic = Diagnostic ;
487
560
type Span = Span ;
561
+ type Term = Term ;
562
+ type TokenNode = TokenNode < Frontend > ;
488
563
each_frontend_method ! ( define_frontend_current_method) ;
489
564
}
490
565
@@ -496,6 +571,8 @@ type CurrentFrontend<'a> = FrontendInterface<
496
571
SourceFile = SourceFile ,
497
572
Diagnostic = Diagnostic ,
498
573
Span = Span ,
574
+ Term = Term ,
575
+ TokenNode = TokenNode < Frontend > ,
499
576
> + ' a ;
500
577
501
578
// Emulate scoped_thread_local!() here essentially
@@ -537,11 +614,11 @@ fn set_current_frontend<F, R>(frontend: &CurrentFrontend, f: F) -> R
537
614
fn erase_concrete_frontend < F , G , R > ( ng : extern "C" fn ( ) -> generation:: Generation ,
538
615
frontend : F ,
539
616
f : G ) -> R
540
- where F : FrontendInterface ,
541
- G : FnOnce ( & CurrentFrontend , & storage :: Storage < F > ) -> R
617
+ where F : FrontendInterface < TokenNode = TokenNode < F > > ,
618
+ G : FnOnce ( & CurrentFrontend , & Storage < F > ) -> R
542
619
{
543
- struct EraseConcrete < F : FrontendInterface > {
544
- storage : storage :: Storage < F > ,
620
+ struct EraseConcrete < F : FrontendInterface < TokenNode = TokenNode < F > > > {
621
+ storage : Storage < F > ,
545
622
concrete : F
546
623
}
547
624
@@ -554,18 +631,20 @@ fn erase_concrete_frontend<F, G, R>(ng: extern "C" fn() -> generation::Generatio
554
631
}
555
632
}
556
633
}
557
- impl < F : FrontendInterface > FrontendInterface for EraseConcrete < F > {
634
+ impl < F : FrontendInterface < TokenNode = TokenNode < F > > > FrontendInterface for EraseConcrete < F > {
558
635
type TokenStream = TokenStream ;
559
636
type TokenStreamBuilder = TokenStreamBuilder ;
560
637
type TokenCursor = TokenCursor ;
561
638
type SourceFile = SourceFile ;
562
639
type Diagnostic = Diagnostic ;
563
640
type Span = Span ;
641
+ type Term = Term ;
642
+ type TokenNode = TokenNode < Frontend > ;
564
643
each_frontend_method ! ( define_frontend_erase_concrete_method) ;
565
644
}
566
645
567
646
let frontend = EraseConcrete {
568
- storage : storage :: Storage :: new ( ng) ,
647
+ storage : Storage :: new ( ng) ,
569
648
concrete : frontend
570
649
} ;
571
650
f ( & frontend, & frontend. storage )
@@ -607,7 +686,7 @@ impl Expand1 {
607
686
}
608
687
609
688
pub fn run < F > ( & self , frontend : F , input : F :: TokenStream ) -> F :: TokenStream
610
- where F : FrontendInterface
689
+ where F : FrontendInterface < TokenNode = TokenNode < F > >
611
690
{
612
691
erase_concrete_frontend ( self . next_generation , frontend, |frontend, storage| {
613
692
let input = storage. from_concrete ( input) ;
@@ -657,7 +736,7 @@ impl Expand2 {
657
736
658
737
pub fn run < F > ( & self , frontend : F , input : F :: TokenStream , input2 : F :: TokenStream )
659
738
-> F :: TokenStream
660
- where F : FrontendInterface
739
+ where F : FrontendInterface < TokenNode = TokenNode < F > >
661
740
{
662
741
erase_concrete_frontend ( self . next_generation , frontend, |frontend, storage| {
663
742
let input = storage. from_concrete ( input) ;
0 commit comments