11use std:: sync:: Arc ;
2- use std:: { fmt, hash as h} ;
2+ use std:: { fmt, hash as h, iter :: zip } ;
33
4- use super :: { hash_str, Hash , NativePredicate , ToFields , Value , F } ;
4+ use anyhow:: { anyhow, Result } ;
5+
6+ use super :: {
7+ hash_str, AnchoredKey , Hash , NativePredicate , PodId , Statement , StatementArg , ToFields , Value ,
8+ F ,
9+ } ;
510
611// BEGIN Custom 1b
712
@@ -11,6 +16,19 @@ pub enum HashOrWildcard {
1116 Wildcard ( usize ) ,
1217}
1318
19+ impl HashOrWildcard {
20+ /// Matches a hash or wildcard against a value, returning a pair
21+ /// representing a wildcard binding (if any) or an error if no
22+ /// match is possible.
23+ pub fn match_against ( & self , v : & Value ) -> Result < Option < ( usize , Value ) > > {
24+ match self {
25+ HashOrWildcard :: Hash ( h) if & Value :: from ( h. clone ( ) ) == v => Ok ( None ) ,
26+ HashOrWildcard :: Wildcard ( i) => Ok ( Some ( ( * i, v. clone ( ) ) ) ) ,
27+ _ => Err ( anyhow ! ( "Failed to match {} against {}." , self , v) ) ,
28+ }
29+ }
30+ }
31+
1432impl fmt:: Display for HashOrWildcard {
1533 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1634 match self {
@@ -27,6 +45,25 @@ pub enum StatementTmplArg {
2745 Key ( HashOrWildcard , HashOrWildcard ) ,
2846}
2947
48+ impl StatementTmplArg {
49+ /// Matches a statement template argument against a statement
50+ /// argument, returning a wildcard correspondence in the case of
51+ /// one or more wildcard matches, nothing in the case of a
52+ /// literal/hash match, and an error otherwise.
53+ pub fn match_against ( & self , s_arg : & StatementArg ) -> Result < Vec < ( usize , Value ) > > {
54+ match ( self , s_arg) {
55+ ( Self :: None , StatementArg :: None ) => Ok ( vec ! [ ] ) ,
56+ ( Self :: Literal ( v) , StatementArg :: Literal ( w) ) if v == w => Ok ( vec ! [ ] ) ,
57+ ( Self :: Key ( tmpl_o, tmpl_k) , StatementArg :: Key ( AnchoredKey ( PodId ( o) , k) ) ) => {
58+ let o_corr = tmpl_o. match_against ( & o. clone ( ) . into ( ) ) ?;
59+ let k_corr = tmpl_k. match_against ( & k. clone ( ) . into ( ) ) ?;
60+ Ok ( [ o_corr, k_corr] . into_iter ( ) . flat_map ( |x| x) . collect ( ) )
61+ }
62+ _ => Err ( anyhow ! ( "Failed to match {} against {}." , self , s_arg) ) ,
63+ }
64+ }
65+ }
66+
3067impl fmt:: Display for StatementTmplArg {
3168 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
3269 match self {
@@ -53,6 +90,33 @@ impl fmt::Display for StatementTmplArg {
5390#[ derive( Clone , Debug , PartialEq , Eq ) ]
5491pub struct StatementTmpl ( pub Predicate , pub Vec < StatementTmplArg > ) ;
5592
93+ impl StatementTmpl {
94+ pub fn pred ( & self ) -> & Predicate {
95+ & self . 0
96+ }
97+ pub fn args ( & self ) -> & [ StatementTmplArg ] {
98+ & self . 1
99+ }
100+ /// Matches a statement template against a statement, returning
101+ /// the variable bindings as an association list. Returns an error
102+ /// if there is type or argument mismatch.
103+ pub fn match_against ( & self , s : & Statement ) -> Result < Vec < ( usize , Value ) > > {
104+ type P = Predicate ;
105+ if matches ! ( self , Self ( P :: BatchSelf ( _) , _) ) {
106+ Err ( anyhow ! (
107+ "Cannot check self-referencing statement templates."
108+ ) )
109+ } else if self . pred ( ) != & s. code ( ) {
110+ Err ( anyhow ! ( "Type mismatch between {:?} and {}." , self , s) )
111+ } else {
112+ zip ( self . args ( ) , s. args ( ) )
113+ . map ( |( t_arg, s_arg) | t_arg. match_against ( & s_arg) )
114+ . collect :: < Result < Vec < _ > > > ( )
115+ . map ( |v| v. concat ( ) )
116+ }
117+ }
118+ }
119+
56120#[ derive( Clone , Debug , PartialEq , Eq ) ]
57121pub struct CustomPredicate {
58122 /// true for "and", false for "or"
0 commit comments