1- use std:: { collections :: BTreeMap , fmt:: Display , ptr:: NonNull } ;
1+ use std:: { fmt:: Display , ptr:: NonNull } ;
22
33use crate :: {
44 Pos , Type ,
@@ -313,9 +313,9 @@ impl Expr {
313313 None
314314 }
315315
316- pub fn as_record ( & self ) -> Option < & Record > {
317- if let Value :: Record ( r ) = & self . value {
318- return Some ( r ) ;
316+ pub fn as_record ( & self ) -> Option < Rec < ' _ > > {
317+ if let Value :: Record ( inner ) = & self . value {
318+ return Some ( Rec { inner } ) ;
319319 }
320320
321321 None
@@ -344,6 +344,18 @@ impl Expr {
344344 visitor. on_var ( & mut node. attrs , var) ?;
345345 }
346346
347+ Value :: Field { label, value } => {
348+ if item. visited {
349+ visitor. exit_field ( & mut node. attrs , label. as_mut_str ( ) , value. as_mut ( ) ) ?;
350+ continue ;
351+ }
352+
353+ item. visited = true ;
354+ visitor. enter_field ( & mut node. attrs , label. as_mut_str ( ) , value. as_mut ( ) ) ?;
355+ stack. push ( item) ;
356+ stack. push ( ItemMut :: new ( value. as_mut ( ) ) ) ;
357+ }
358+
347359 Value :: Record ( record) => {
348360 if item. visited {
349361 visitor. exit_record ( & mut node. attrs , record) ?;
@@ -354,8 +366,7 @@ impl Expr {
354366 visitor. enter_record ( & mut node. attrs , record) ?;
355367 stack. push ( item) ;
356368
357- for ( key, expr) in record. fields . iter_mut ( ) {
358- visitor. enter_record_entry ( & mut node. attrs , key, expr) ?;
369+ for expr in record. iter_mut ( ) . rev ( ) {
359370 stack. push ( ItemMut :: new ( expr) ) ;
360371 }
361372 }
@@ -433,6 +444,18 @@ impl Expr {
433444 visitor. on_var ( & item. value . attrs , var) ;
434445 }
435446
447+ Value :: Field { label, value } => {
448+ if item. visited {
449+ visitor. exit_field ( & item. value . attrs , label. as_str ( ) , value) ;
450+ continue ;
451+ }
452+
453+ item. visited = true ;
454+ visitor. enter_field ( & item. value . attrs , label. as_str ( ) , value) ;
455+ stack. push ( item) ;
456+ stack. push ( Item :: new ( value) ) ;
457+ }
458+
436459 Value :: Record ( record) => {
437460 if item. visited {
438461 visitor. exit_record ( & item. value . attrs , record) ;
@@ -441,11 +464,9 @@ impl Expr {
441464
442465 item. visited = true ;
443466 visitor. enter_record ( & item. value . attrs , record) ;
444- let attrs = & item. value . attrs ;
445467 stack. push ( item) ;
446468
447- for ( key, expr) in record. fields . iter ( ) {
448- visitor. enter_record_entry ( attrs, key, expr) ;
469+ for expr in record. iter ( ) . rev ( ) {
449470 stack. push ( Item :: new ( expr) ) ;
450471 }
451472 }
@@ -548,6 +569,24 @@ pub struct UnaryOp<'a> {
548569 pub expr : & ' a Expr ,
549570}
550571
572+ pub struct Rec < ' a > {
573+ inner : & ' a Vec < Expr > ,
574+ }
575+
576+ impl Rec < ' _ > {
577+ pub fn get ( & self , id : & str ) -> Option < & Expr > {
578+ for expr in self . inner . iter ( ) {
579+ if let Value :: Field { label, value } = & expr. value
580+ && label == id
581+ {
582+ return Some ( value) ;
583+ }
584+ }
585+
586+ None
587+ }
588+ }
589+
551590pub struct ApplyFun < ' a > {
552591 pub name : & ' a String ,
553592 pub params : & ' a Vec < Expr > ,
@@ -573,34 +612,35 @@ impl Display for Var {
573612
574613pub enum Value {
575614 Literal ( Literal ) ,
615+
576616 Var ( Var ) ,
577- Record ( Record ) ,
617+
618+ Field {
619+ label : String ,
620+ value : Box < Expr > ,
621+ } ,
622+
623+ Record ( Vec < Expr > ) ,
624+
578625 Array ( Vec < Expr > ) ,
626+
579627 App {
580628 fun : String ,
581629 params : Vec < Expr > ,
582630 } ,
631+
583632 Binary {
584633 lhs : Box < Expr > ,
585634 op : Operation ,
586635 rhs : Box < Expr > ,
587636 } ,
637+
588638 Unary {
589639 op : Operation ,
590640 expr : Box < Expr > ,
591641 } ,
592642}
593643
594- pub struct Record {
595- pub fields : BTreeMap < String , Expr > ,
596- }
597-
598- impl Record {
599- pub fn get ( & self , id : & str ) -> Option < & Expr > {
600- self . fields . get ( id)
601- }
602- }
603-
604644pub struct Sort {
605645 pub expr : Expr ,
606646 pub order : Order ,
@@ -746,24 +786,33 @@ pub trait ExprVisitorMut {
746786 fn enter_record (
747787 & mut self ,
748788 attrs : & mut NodeAttributes ,
749- record : & mut Record ,
789+ record : & mut [ Expr ] ,
750790 ) -> crate :: Result < ( ) > {
751791 Ok ( ( ) )
752792 }
753793
754- fn enter_record_entry (
794+ fn enter_field (
755795 & mut self ,
756796 attrs : & mut NodeAttributes ,
757- key : & str ,
758- expr : & mut Expr ,
797+ label : & mut str ,
798+ value : & mut Expr ,
799+ ) -> crate :: Result < ( ) > {
800+ Ok ( ( ) )
801+ }
802+
803+ fn exit_field (
804+ & mut self ,
805+ attrs : & mut NodeAttributes ,
806+ label : & mut str ,
807+ value : & mut Expr ,
759808 ) -> crate :: Result < ( ) > {
760809 Ok ( ( ) )
761810 }
762811
763812 fn exit_record (
764813 & mut self ,
765814 attrs : & mut NodeAttributes ,
766- record : & mut Record ,
815+ record : & mut [ Expr ] ,
767816 ) -> crate :: Result < ( ) > {
768817 Ok ( ( ) )
769818 }
@@ -872,9 +921,10 @@ pub trait QueryVisitor {
872921pub trait ExprVisitor {
873922 fn on_literal ( & mut self , attrs : & NodeAttributes , lit : & Literal ) { }
874923 fn on_var ( & mut self , attrs : & NodeAttributes , var : & Var ) { }
875- fn enter_record ( & mut self , attrs : & NodeAttributes , record : & Record ) { }
876- fn enter_record_entry ( & mut self , attrs : & NodeAttributes , key : & str , expr : & Expr ) { }
877- fn exit_record ( & mut self , attrs : & NodeAttributes , record : & Record ) { }
924+ fn enter_record ( & mut self , attrs : & NodeAttributes , record : & [ Expr ] ) { }
925+ fn enter_field ( & mut self , attrs : & NodeAttributes , label : & str , value : & Expr ) { }
926+ fn exit_field ( & mut self , attrs : & NodeAttributes , label : & str , value : & Expr ) { }
927+ fn exit_record ( & mut self , attrs : & NodeAttributes , record : & [ Expr ] ) { }
878928 fn enter_array ( & mut self , attrs : & NodeAttributes , values : & [ Expr ] ) { }
879929 fn exit_array ( & mut self , attrs : & NodeAttributes , values : & [ Expr ] ) { }
880930 fn enter_app ( & mut self , attrs : & NodeAttributes , name : & str , params : & [ Expr ] ) { }
0 commit comments