@@ -33,6 +33,62 @@ impl<T> AnnotFormula<T> {
3333 }
3434}
3535
36+ /// A path in an annotation.
37+ ///
38+ /// Handling of paths in Thrust annotations is intentionally limited now. We plan to re-implement
39+ /// annotation parsing while letting rustc handle path resolution in the future.
40+ #[ derive( Debug , Clone ) ]
41+ pub struct AnnotPath {
42+ pub segments : Vec < AnnotPathSegment > ,
43+ }
44+
45+ impl AnnotPath {
46+ /// Convert the path to a datatype constructor term with the given arguments.
47+ pub fn to_datatype_ctor < V > ( & self , ctor_args : Vec < chc:: Term < V > > ) -> ( chc:: Term < V > , chc:: Sort ) {
48+ let mut segments = self . segments . clone ( ) ;
49+
50+ let ctor = segments. pop ( ) . unwrap ( ) ;
51+ if !ctor. generic_args . is_empty ( ) {
52+ unimplemented ! ( "generic arguments in datatype constructor" ) ;
53+ }
54+ let Some ( ty_last_segment) = segments. last_mut ( ) else {
55+ unimplemented ! ( "single segment path" ) ;
56+ } ;
57+ let generic_args: Vec < _ > = ty_last_segment. generic_args . drain ( ..) . collect ( ) ;
58+ let ty_path_idents: Vec < _ > = segments
59+ . into_iter ( )
60+ . map ( |segment| {
61+ if !segment. generic_args . is_empty ( ) {
62+ unimplemented ! ( "generic arguments in datatype constructor" ) ;
63+ }
64+ segment. ident . to_string ( )
65+ } )
66+ . collect ( ) ;
67+ // see refine::datatype_symbol
68+ let d_sym = chc:: DatatypeSymbol :: new ( ty_path_idents. join ( "." ) ) ;
69+ let v_sym = chc:: DatatypeSymbol :: new ( format ! ( "{}.{}" , d_sym, ctor. ident. as_str( ) ) ) ;
70+ let term = chc:: Term :: datatype_ctor ( d_sym. clone ( ) , generic_args. clone ( ) , v_sym, ctor_args) ;
71+ let sort = chc:: Sort :: datatype ( d_sym, generic_args) ;
72+ ( term, sort)
73+ }
74+
75+ /// If the path consists of a single segment without generic arguments, return that identifier.
76+ pub fn single_segment_ident ( & self ) -> Option < & Ident > {
77+ if self . segments . len ( ) == 1 && self . segments [ 0 ] . generic_args . is_empty ( ) {
78+ Some ( & self . segments [ 0 ] . ident )
79+ } else {
80+ None
81+ }
82+ }
83+ }
84+
85+ /// A segment of a path in an annotation.
86+ #[ derive( Debug , Clone ) ]
87+ pub struct AnnotPathSegment {
88+ pub ident : Ident ,
89+ pub generic_args : Vec < chc:: Sort > ,
90+ }
91+
3692/// A trait for resolving variables in annotations to their logical representation and their sorts.
3793pub trait Resolver {
3894 type Output ;
@@ -298,6 +354,88 @@ where
298354 }
299355 }
300356
357+ fn parse_path_tail ( & mut self , head : Ident ) -> Result < AnnotPath > {
358+ let mut segments: Vec < AnnotPathSegment > = Vec :: new ( ) ;
359+ segments. push ( AnnotPathSegment {
360+ ident : head,
361+ generic_args : Vec :: new ( ) ,
362+ } ) ;
363+ while let Some ( Token {
364+ kind : TokenKind :: ModSep ,
365+ ..
366+ } ) = self . look_ahead_token ( 0 )
367+ {
368+ self . consume ( ) ;
369+ match self . next_token ( "ident or <" ) ? {
370+ t @ Token {
371+ kind : TokenKind :: Lt ,
372+ ..
373+ } => {
374+ if segments. is_empty ( ) {
375+ return Err ( ParseAttrError :: unexpected_token (
376+ "path segment before <" ,
377+ t. clone ( ) ,
378+ ) ) ;
379+ }
380+ let mut generic_args = Vec :: new ( ) ;
381+ loop {
382+ let sort = self . parse_sort ( ) ?;
383+ generic_args. push ( sort) ;
384+ match self . next_token ( ", or >" ) ? {
385+ Token {
386+ kind : TokenKind :: Comma ,
387+ ..
388+ } => { }
389+ Token {
390+ kind : TokenKind :: Gt ,
391+ ..
392+ } => break ,
393+ t => return Err ( ParseAttrError :: unexpected_token ( ", or >" , t. clone ( ) ) ) ,
394+ }
395+ }
396+ segments. last_mut ( ) . unwrap ( ) . generic_args = generic_args;
397+ }
398+ t @ Token {
399+ kind : TokenKind :: Ident ( _, _) ,
400+ ..
401+ } => {
402+ let ( ident, _) = t. ident ( ) . unwrap ( ) ;
403+ segments. push ( AnnotPathSegment {
404+ ident,
405+ generic_args : Vec :: new ( ) ,
406+ } ) ;
407+ }
408+ t => return Err ( ParseAttrError :: unexpected_token ( "ident or <" , t. clone ( ) ) ) ,
409+ }
410+ }
411+ Ok ( AnnotPath { segments } )
412+ }
413+
414+ fn parse_datatype_ctor_args ( & mut self ) -> Result < Vec < chc:: Term < T :: Output > > > {
415+ if self . look_ahead_token ( 0 ) . is_none ( ) {
416+ return Ok ( Vec :: new ( ) ) ;
417+ }
418+
419+ let mut terms = Vec :: new ( ) ;
420+ loop {
421+ let formula_or_term = self . parse_formula_or_term ( ) ?;
422+ let ( t, _) = formula_or_term. into_term ( ) . ok_or_else ( || {
423+ ParseAttrError :: unexpected_formula ( "in datatype constructor arguments" )
424+ } ) ?;
425+ terms. push ( t) ;
426+ if let Some ( Token {
427+ kind : TokenKind :: Comma ,
428+ ..
429+ } ) = self . look_ahead_token ( 0 )
430+ {
431+ self . consume ( ) ;
432+ } else {
433+ break ;
434+ }
435+ }
436+ Ok ( terms)
437+ }
438+
301439 fn parse_atom ( & mut self ) -> Result < FormulaOrTerm < T :: Output > > {
302440 let tt = self . next_token_tree ( "term or formula" ) ?. clone ( ) ;
303441
@@ -317,21 +455,43 @@ where
317455 } ;
318456
319457 let formula_or_term = if let Some ( ( ident, _) ) = t. ident ( ) {
320- match (
321- ident. as_str ( ) ,
322- self . formula_existentials . get ( ident. name . as_str ( ) ) ,
323- ) {
324- ( "true" , _) => FormulaOrTerm :: Formula ( chc:: Formula :: top ( ) ) ,
325- ( "false" , _) => FormulaOrTerm :: Formula ( chc:: Formula :: bottom ( ) ) ,
326- ( _, Some ( sort) ) => {
327- let var =
328- chc:: Term :: FormulaExistentialVar ( sort. clone ( ) , ident. name . to_string ( ) ) ;
329- FormulaOrTerm :: Term ( var, sort. clone ( ) )
330- }
331- _ => {
332- let ( v, sort) = self . resolve ( ident) ?;
333- FormulaOrTerm :: Term ( chc:: Term :: var ( v) , sort)
458+ let path = self . parse_path_tail ( ident) ?;
459+ if let Some ( ident) = path. single_segment_ident ( ) {
460+ match (
461+ ident. as_str ( ) ,
462+ self . formula_existentials . get ( ident. name . as_str ( ) ) ,
463+ ) {
464+ ( "true" , _) => FormulaOrTerm :: Formula ( chc:: Formula :: top ( ) ) ,
465+ ( "false" , _) => FormulaOrTerm :: Formula ( chc:: Formula :: bottom ( ) ) ,
466+ ( _, Some ( sort) ) => {
467+ let var =
468+ chc:: Term :: FormulaExistentialVar ( sort. clone ( ) , ident. name . to_string ( ) ) ;
469+ FormulaOrTerm :: Term ( var, sort. clone ( ) )
470+ }
471+ _ => {
472+ let ( v, sort) = self . resolve ( * ident) ?;
473+ FormulaOrTerm :: Term ( chc:: Term :: var ( v) , sort)
474+ }
334475 }
476+ } else {
477+ let next_tt = self
478+ . next_token_tree ( "arguments for datatype constructor" ) ?
479+ . clone ( ) ;
480+ let TokenTree :: Delimited ( _, _, Delimiter :: Parenthesis , s) = next_tt else {
481+ return Err ( ParseAttrError :: unexpected_token_tree (
482+ "arguments for datatype constructor" ,
483+ next_tt. clone ( ) ,
484+ ) ) ;
485+ } ;
486+ let mut parser = Parser {
487+ resolver : self . boxed_resolver ( ) ,
488+ cursor : s. trees ( ) ,
489+ formula_existentials : self . formula_existentials . clone ( ) ,
490+ } ;
491+ let args = parser. parse_datatype_ctor_args ( ) ?;
492+ parser. end_of_input ( ) ?;
493+ let ( term, sort) = path. to_datatype_ctor ( args) ;
494+ FormulaOrTerm :: Term ( term, sort)
335495 }
336496 } else {
337497 match t. kind {
0 commit comments