@@ -1145,7 +1145,7 @@ impl<'a, C: Clone> TranslatorHandle<'a, C> {
11451145 output : & mut OutputAst ,
11461146 user_ctx : & mut C ,
11471147 id : Id ,
1148- ) -> Result < Vec < OutputId > , String > {
1148+ ) -> Vec < OutputId > {
11491149 apply_rules_inner (
11501150 self . index ,
11511151 ast,
@@ -1163,10 +1163,10 @@ impl<'a, C: Clone> TranslatorHandle<'a, C> {
11631163 output : & mut OutputAst ,
11641164 user_ctx : & mut C ,
11651165 skip : & [ & str ] ,
1166- ) -> Result < TranslatedCaptures , String > {
1167- captures. try_translate_except ( skip, |id| {
1166+ ) -> TranslatedCaptures {
1167+ captures. translate_except ( skip, |id| {
11681168 if id == self . matched_root {
1169- Err ( "cannot eagerly translate a capture of the matched rule root" . to_string ( ) )
1169+ panic ! ( "cannot eagerly translate a capture of the matched rule root" )
11701170 } else {
11711171 self . translate ( ast, output, user_ctx, id)
11721172 }
@@ -1178,7 +1178,7 @@ impl<'a, C: Clone> TranslatorHandle<'a, C> {
11781178///
11791179/// Takes the immutable input AST, mutable output AST, raw captured variables,
11801180/// source range of the matched node, mutable user context, and a
1181- /// [`TranslatorHandle`]. Returns output IDs or an error .
1181+ /// [`TranslatorHandle`]. Returns output IDs.
11821182///
11831183/// Transforms receive raw input captures. Macro-generated transforms eagerly
11841184/// translate `@` captures and translate raw ids when they are returned or
@@ -1191,7 +1191,7 @@ pub type Transform<C = ()> = Box<
11911191 Option < Range > ,
11921192 & mut C ,
11931193 TranslatorHandle < ' _ , C > ,
1194- ) -> Result < Vec < OutputId > , String >
1194+ ) -> Vec < OutputId >
11951195 + Send
11961196 + Sync ,
11971197> ;
@@ -1200,7 +1200,7 @@ pub type Transform<C = ()> = Box<
12001200/// runs. Returning `false` makes the rule behave as if its query did not
12011201/// match, so the driver continues to the next rule. Guards have read-only
12021202/// access to the shared user context.
1203- pub type Guard < C = ( ) > = Box < dyn Fn ( & Ast , & Captures , & C ) -> Result < bool , String > + Send + Sync > ;
1203+ pub type Guard < C = ( ) > = Box < dyn Fn ( & Ast , & Captures , & C ) -> bool + Send + Sync > ;
12041204
12051205pub struct Rule < C = ( ) > {
12061206 query : QueryNode ,
@@ -1238,21 +1238,21 @@ impl<C> Rule<C> {
12381238 /// Attempt to match this rule's query against `node`, returning the raw
12391239 /// captures on success. Does not evaluate the guard or invoke the
12401240 /// transform.
1241- fn match_query ( & self , ast : & Ast , node : Id ) -> Result < Option < Captures > , String > {
1241+ fn match_query ( & self , ast : & Ast , node : Id ) -> Option < Captures > {
12421242 let mut captures = Captures :: new ( ) ;
1243- if !self . query . do_match ( ast, node, & mut captures) ? {
1244- return Ok ( None ) ;
1243+ if !self . query . do_match ( ast, node, & mut captures) {
1244+ return None ;
12451245 }
1246- Ok ( Some ( captures) )
1246+ Some ( captures)
12471247 }
12481248
12491249 /// Evaluate this rule's guard against a successful query match. An
12501250 /// unguarded rule always succeeds.
1251- fn guard_matches ( & self , ast : & Ast , captures : & Captures , user_ctx : & C ) -> Result < bool , String > {
1251+ fn guard_matches ( & self , ast : & Ast , captures : & Captures , user_ctx : & C ) -> bool {
12521252 if let Some ( guard) = & self . guard {
12531253 guard ( ast, captures, user_ctx)
12541254 } else {
1255- Ok ( true )
1255+ true
12561256 }
12571257 }
12581258
@@ -1266,7 +1266,7 @@ impl<C> Rule<C> {
12661266 node : Id ,
12671267 user_ctx : & mut C ,
12681268 translator : TranslatorHandle < ' _ , C > ,
1269- ) -> Result < Vec < OutputId > , String > {
1269+ ) -> Vec < OutputId > {
12701270 let source_range = ast. source_range_ignoring_fields ( node, & self . ignored_location_fields ) ;
12711271 ( self . transform ) ( ast, output, captures, source_range, user_ctx, translator)
12721272 }
@@ -1306,14 +1306,14 @@ impl<'a, C> RuleIndex<'a, C> {
13061306
13071307/// Apply the first matching rule to each visited node. Recursion proceeds
13081308/// only through captured nodes (not through the input node's children
1309- /// directly), and an error is returned if no rule matches a visited node.
1309+ /// directly), and panics if no rule matches a visited node.
13101310fn apply_rules < C : Clone > (
13111311 rules : & [ Rule < C > ] ,
13121312 ast : & Ast ,
13131313 output : & mut OutputAst ,
13141314 user_ctx : & mut C ,
13151315 id : Id ,
1316- ) -> Result < Vec < OutputId > , String > {
1316+ ) -> Vec < OutputId > {
13171317 let index = RuleIndex :: new ( rules) ;
13181318 apply_rules_inner ( & index, ast, output, user_ctx, id, 0 )
13191319}
@@ -1325,22 +1325,22 @@ fn apply_rules_inner<C: Clone>(
13251325 user_ctx : & mut C ,
13261326 id : Id ,
13271327 rewrite_depth : usize ,
1328- ) -> Result < Vec < OutputId > , String > {
1328+ ) -> Vec < OutputId > {
13291329 if rewrite_depth > MAX_REWRITE_DEPTH {
1330- return Err ( format ! (
1330+ panic ! (
13311331 "Desugaring exceeded maximum rewrite depth ({MAX_REWRITE_DEPTH}). \
13321332 This likely indicates a non-terminating rule cycle."
1333- ) ) ;
1333+ ) ;
13341334 }
13351335
13361336 let node_kind = ast. get_node ( id) . map ( |n| n. kind_name ( ) ) . unwrap_or ( "" ) ;
13371337
13381338 for rule in index. rules_for_kind ( node_kind) {
1339- let Some ( captures) = rule. match_query ( ast, id) ? else {
1339+ let Some ( captures) = rule. match_query ( ast, id) else {
13401340 continue ;
13411341 } ;
13421342
1343- if !rule. guard_matches ( ast, & captures, user_ctx) ? {
1343+ if !rule. guard_matches ( ast, & captures, user_ctx) {
13441344 continue ;
13451345 }
13461346
@@ -1355,11 +1355,11 @@ fn apply_rules_inner<C: Clone>(
13551355 rewrite_depth,
13561356 matched_root : id,
13571357 } ;
1358- let result = rule. run_transform ( ast, output, captures, id, & mut local, translator) ? ;
1359- return Ok ( result) ;
1358+ let result = rule. run_transform ( ast, output, captures, id, & mut local, translator) ;
1359+ return result;
13601360 }
13611361
1362- Err ( format ! ( "no rule matched node of kind '{node_kind}'" ) )
1362+ panic ! ( "no rule matched node of kind '{node_kind}'" )
13631363}
13641364
13651365/// A named bundle of exhaustive rules for the one-shot translation pass.
@@ -1617,23 +1617,40 @@ impl<'a, C: Clone> Runner<'a, C> {
16171617 }
16181618
16191619 fn run_once ( & self , ast : Ast , user_ctx : & mut C ) -> Result < OutputAst , String > {
1620- if self . phases . len ( ) != 1 {
1621- return Err ( "YEAST requires exactly one translation phase" . to_string ( ) ) ;
1622- }
1620+ std:: panic:: catch_unwind ( std:: panic:: AssertUnwindSafe ( || {
1621+ self . run_once_inner ( ast, user_ctx)
1622+ } ) )
1623+ . map ( Ok )
1624+ . unwrap_or_else ( |payload| {
1625+ let message = if let Some ( message) = payload. downcast_ref :: < & str > ( ) {
1626+ ( * message) . to_owned ( )
1627+ } else if let Some ( message) = payload. downcast_ref :: < String > ( ) {
1628+ message. clone ( )
1629+ } else {
1630+ "unknown panic payload" . to_owned ( )
1631+ } ;
1632+ Err ( format ! ( "YEAST translation panicked: {message}" ) )
1633+ } )
1634+ }
1635+
1636+ fn run_once_inner ( & self , ast : Ast , user_ctx : & mut C ) -> OutputAst {
1637+ assert_eq ! (
1638+ self . phases. len( ) ,
1639+ 1 ,
1640+ "YEAST requires exactly one translation phase"
1641+ ) ;
16231642 let phase = & self . phases [ 0 ] ;
16241643 let mut output = OutputAst :: with_schema ( self . schema . clone ( ) ) ;
1625- let res = apply_rules ( & phase. rules , & ast, & mut output, user_ctx, ast. get_root ( ) )
1626- . map_err ( |e| format ! ( "Phase `{}`: {e}" , phase. name) ) ?;
1627- if res. len ( ) != 1 {
1628- return Err ( format ! (
1629- "Phase `{}`: expected exactly one result node, got {}" ,
1630- phase. name,
1631- res. len( )
1632- ) ) ;
1633- }
1644+ let res = apply_rules ( & phase. rules , & ast, & mut output, user_ctx, ast. get_root ( ) ) ;
1645+ assert_eq ! (
1646+ res. len( ) ,
1647+ 1 ,
1648+ "expected exactly one result node, got {}" ,
1649+ res. len( )
1650+ ) ;
16341651 output. set_root ( res[ 0 ] ) ;
16351652 output. set_source ( ast. into_source ( ) ) ;
1636- Ok ( output)
1653+ output
16371654 }
16381655}
16391656
0 commit comments