@@ -3,6 +3,7 @@ use std::sync::Arc;
3
3
use fxhash:: FxHashMap ;
4
4
use scoped_arena:: Scope ;
5
5
6
+ use super :: semantics:: { LazyValue , LocalExprs } ;
6
7
use crate :: core:: semantics:: { ArcValue , Elim , ElimEnv , Head , Value } ;
7
8
use crate :: core:: { self , Const , Plicity , Prim , UIntStyle } ;
8
9
use crate :: env:: { self , SharedEnv , UniqueEnv } ;
@@ -508,8 +509,8 @@ struct EnvBuilder<'arena> {
508
509
entries : FxHashMap < Symbol , ( Prim , ArcValue < ' arena > ) > ,
509
510
scope : & ' arena Scope < ' arena > ,
510
511
meta_exprs : UniqueEnv < Option < ArcValue < ' arena > > > ,
511
- item_exprs : UniqueEnv < ArcValue < ' arena > > ,
512
- local_exprs : SharedEnv < ArcValue < ' arena > > ,
512
+ item_exprs : UniqueEnv < LazyValue < ' arena > > ,
513
+ local_exprs : LocalExprs < ' arena > ,
513
514
}
514
515
515
516
impl < ' arena > EnvBuilder < ' arena > {
@@ -577,13 +578,13 @@ macro_rules! step {
577
578
// TODO: Should we merge the spans of the param idents to produce the body span?
578
579
macro_rules! const_step {
579
580
( [ $( $param: ident : $Input: ident) ,* ] => $body: expr) => {
580
- step!( _ , [ $( $param) ,* ] => match ( $( $param. as_ref( ) , ) * ) {
581
+ step!( env , [ $( $param) ,* ] => match ( $( env . force_lazy ( $param) . as_ref( ) , ) * ) {
581
582
( $( Value :: ConstLit ( Const :: $Input( $param, ..) ) , ) * ) => Spanned :: empty( Arc :: new( Value :: ConstLit ( $body) ) ) ,
582
583
_ => return None ,
583
584
} )
584
585
} ;
585
586
( [ $( $param: ident , $style: ident : $Input: ident) ,* ] => $body: expr) => {
586
- step!( _ , [ $( $param) ,* ] => match ( $( $param. as_ref( ) , ) * ) {
587
+ step!( env , [ $( $param) ,* ] => match ( $( env . force_lazy ( $param) . as_ref( ) , ) * ) {
587
588
( $( Value :: ConstLit ( Const :: $Input( $param, $style) ) , ) * ) => Spanned :: empty( Arc :: new( Value :: ConstLit ( $body) ) ) ,
588
589
_ => return None ,
589
590
} )
@@ -611,21 +612,18 @@ pub fn repr(prim: Prim) -> Step {
611
612
Prim :: FormatF32Le => step ! ( _, [ ] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: F32Type , [ ] ) ) ) ) ,
612
613
Prim :: FormatF64Be => step ! ( _, [ ] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: F64Type , [ ] ) ) ) ) ,
613
614
Prim :: FormatF64Le => step ! ( _, [ ] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: F64Type , [ ] ) ) ) ) ,
614
- Prim :: FormatRepeatLen8 => step ! ( env, [ len, elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: Array8Type , [ len. clone( ) , env. format_repr( elem) ] ) ) ) ) ,
615
- Prim :: FormatRepeatLen16 => step ! ( env, [ len, elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: Array16Type , [ len. clone( ) , env. format_repr( elem) ] ) ) ) ) ,
616
- Prim :: FormatRepeatLen32 => step ! ( env, [ len, elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: Array32Type , [ len. clone( ) , env. format_repr( elem) ] ) ) ) ) ,
617
- Prim :: FormatRepeatLen64 => step ! ( env, [ len, elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: Array64Type , [ len. clone( ) , env. format_repr( elem) ] ) ) ) ) ,
618
- Prim :: FormatLimit8 => step ! ( env, [ _, elem] => env. format_repr( elem) ) ,
619
- Prim :: FormatLimit16 => step ! ( env, [ _, elem] => env. format_repr( elem) ) ,
620
- Prim :: FormatLimit32 => step ! ( env, [ _, elem] => env. format_repr( elem) ) ,
621
- Prim :: FormatLimit64 => step ! ( env, [ _, elem] => env. format_repr( elem) ) ,
622
- Prim :: FormatRepeatUntilEnd => step ! ( env, [ elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: ArrayType , [ env. format_repr( elem) ] ) ) ) ) ,
623
- Prim :: FormatLink => step ! ( _, [ _, elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: RefType , [ elem. clone( ) ] ) ) ) ) ,
624
- Prim :: FormatDeref => step ! ( env, [ elem, _] => env. format_repr( elem) ) ,
615
+ Prim :: FormatRepeatLen8 => step ! ( env, [ len, elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: Array8Type , [ env. force_lazy( len) , env. format_repr( & env. force_lazy( elem) ) ] ) ) ) ) ,
616
+ Prim :: FormatRepeatLen16 => step ! ( env, [ len, elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: Array16Type , [ env. force_lazy( len) , env. format_repr( & env. force_lazy( elem) ) ] ) ) ) ) ,
617
+ Prim :: FormatRepeatLen32 => step ! ( env, [ len, elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: Array32Type , [ env. force_lazy( len) , env. format_repr( & env. force_lazy( elem) ) ] ) ) ) ) ,
618
+ Prim :: FormatRepeatLen64 => step ! ( env, [ len, elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: Array64Type , [ env. force_lazy( len) , env. format_repr( & env. force_lazy( elem) ) ] ) ) ) ) ,
619
+ Prim :: FormatLimit8 | Prim :: FormatLimit16 | Prim :: FormatLimit32 | Prim :: FormatLimit64 => step ! ( env, [ _, elem] => env. format_repr( & env. force_lazy( elem) ) ) ,
620
+ Prim :: FormatRepeatUntilEnd => step ! ( env, [ elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: ArrayType , [ env. format_repr( & env. force_lazy( elem) ) ] ) ) ) ) ,
621
+ Prim :: FormatLink => step ! ( env, [ _, elem] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: RefType , [ env. force_lazy( elem) ] ) ) ) ) ,
622
+ Prim :: FormatDeref => step ! ( env, [ elem, _] => env. format_repr( & env. force_lazy( elem) ) ) ,
625
623
Prim :: FormatStreamPos => step ! ( _, [ ] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: PosType , [ ] ) ) ) ) ,
626
- Prim :: FormatSucceed => step ! ( _ , [ elem, _] => elem . clone ( ) ) ,
624
+ Prim :: FormatSucceed => step ! ( env , [ elem, _] => env . force_lazy ( elem ) ) ,
627
625
Prim :: FormatFail => step ! ( _, [ ] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: VoidType , [ ] ) ) ) ) ,
628
- Prim :: FormatUnwrap => step ! ( _ , [ elem, _] => elem . clone ( ) ) ,
626
+ Prim :: FormatUnwrap => step ! ( env , [ elem, _] => env . force_lazy ( elem ) ) ,
629
627
Prim :: ReportedError => step ! ( _, [ ] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: ReportedError , [ ] ) ) ) ) ,
630
628
_ => |_, _| None ,
631
629
}
@@ -641,15 +639,49 @@ pub fn step(prim: Prim) -> Step {
641
639
#[ allow( unreachable_code) ]
642
640
Prim :: Absurd => step ! ( _, [ _, _] => panic!( "Constructed an element of `Void`" ) ) ,
643
641
644
- Prim :: FormatRepr => step ! ( env, [ format] => env. format_repr( format) ) ,
642
+ Prim :: FormatRepr => step ! ( env, [ format] => env. format_repr( & env . force_lazy ( format) ) ) ,
645
643
646
644
Prim :: BoolEq => const_step ! ( [ x: Bool , y: Bool ] => Const :: Bool ( x == y) ) ,
647
645
Prim :: BoolNeq => const_step ! ( [ x: Bool , y: Bool ] => Const :: Bool ( x != y) ) ,
648
646
Prim :: BoolNot => const_step ! ( [ x: Bool ] => Const :: Bool ( bool :: not( * x) ) ) ,
649
- Prim :: BoolAnd => const_step ! ( [ x: Bool , y: Bool ] => Const :: Bool ( * x && * y) ) ,
650
- Prim :: BoolOr => const_step ! ( [ x: Bool , y: Bool ] => Const :: Bool ( * x || * y) ) ,
651
647
Prim :: BoolXor => const_step ! ( [ x: Bool , y: Bool ] => Const :: Bool ( * x ^ * y) ) ,
652
648
649
+ Prim :: BoolAnd => |env : & ElimEnv , spine : & [ Elim ] | match spine {
650
+ [ Elim :: FunApp ( _, x) , Elim :: FunApp ( _, y) ] => {
651
+ let x = env. force_lazy ( x) ;
652
+ match x. as_ref ( ) {
653
+ Value :: ConstLit ( Const :: Bool ( false ) ) => Some ( x) ,
654
+ Value :: ConstLit ( Const :: Bool ( true ) ) => {
655
+ let y = env. force_lazy ( y) ;
656
+ match y. as_ref ( ) {
657
+ Value :: ConstLit ( Const :: Bool ( _) ) => Some ( y) ,
658
+ _ => None ,
659
+ }
660
+ }
661
+ _ => None ,
662
+ }
663
+ }
664
+ _ => None ,
665
+ } ,
666
+
667
+ Prim :: BoolOr => |env : & ElimEnv , spine : & [ Elim ] | match spine {
668
+ [ Elim :: FunApp ( _, x) , Elim :: FunApp ( _, y) ] => {
669
+ let x = env. force_lazy ( x) ;
670
+ match x. as_ref ( ) {
671
+ Value :: ConstLit ( Const :: Bool ( true ) ) => Some ( x) ,
672
+ Value :: ConstLit ( Const :: Bool ( false ) ) => {
673
+ let y = env. force_lazy ( y) ;
674
+ match y. as_ref ( ) {
675
+ Value :: ConstLit ( Const :: Bool ( _) ) => Some ( y) ,
676
+ _ => None ,
677
+ }
678
+ }
679
+ _ => None ,
680
+ }
681
+ }
682
+ _ => None ,
683
+ } ,
684
+
653
685
Prim :: U8Eq => const_step ! ( [ x: U8 , y: U8 ] => Const :: Bool ( x == y) ) ,
654
686
Prim :: U8Neq => const_step ! ( [ x: U8 , y: U8 ] => Const :: Bool ( x != y) ) ,
655
687
Prim :: U8Gt => const_step ! ( [ x: U8 , y: U8 ] => Const :: Bool ( x > y) ) ,
@@ -775,22 +807,20 @@ pub fn step(prim: Prim) -> Step {
775
807
Prim :: S64UAbs => const_step ! ( [ x: S64 ] => Const :: U64 ( i64 :: unsigned_abs( * x) , UIntStyle :: Decimal ) ) ,
776
808
777
809
Prim :: OptionFold => step ! ( env, [ _, _, on_none, on_some, option] => {
778
- match option. match_prim_spine( ) ? {
810
+ match env . force_lazy ( option) . match_prim_spine( ) ? {
779
811
( Prim :: OptionSome , [ _, Elim :: FunApp ( Plicity :: Explicit , value) ] ) => {
780
- env. fun_app( Plicity :: Explicit , on_some . clone ( ) , value. clone ( ) )
812
+ env. fun_app( Plicity :: Explicit , env . force_lazy ( on_some ) , value)
781
813
} ,
782
- ( Prim :: OptionNone , [ _] ) => on_none . clone ( ) ,
814
+ ( Prim :: OptionNone , [ _] ) => env . force_lazy ( on_none ) ,
783
815
_ => return None ,
784
816
}
785
817
} ) ,
786
818
787
819
Prim :: Array8Find | Prim :: Array16Find | Prim :: Array32Find | Prim :: Array64Find => {
788
- step ! ( env, [ _, elem_type, pred, array] => match array. as_ref( ) {
820
+ step ! ( env, [ _, elem_type, pred, array] => match env . force_lazy ( array) . as_ref( ) {
789
821
Value :: ArrayLit ( elems) => {
790
822
for elem in elems {
791
- match env. fun_app(
792
- Plicity :: Explicit ,
793
- pred. clone( ) , elem. clone( ) ) . as_ref( ) {
823
+ match env. fun_app( Plicity :: Explicit , env. force_lazy( pred) , elem) . as_ref( ) {
794
824
Value :: ConstLit ( Const :: Bool ( true ) ) => {
795
825
return Some ( Spanned :: empty( Arc :: new( Value :: Stuck (
796
826
Head :: Prim ( Prim :: OptionSome ) ,
@@ -814,16 +844,16 @@ pub fn step(prim: Prim) -> Step {
814
844
}
815
845
816
846
Prim :: Array8Index | Prim :: Array16Index | Prim :: Array32Index | Prim :: Array64Index => {
817
- step ! ( _ , [ _, _, index, array] => match array. as_ref( ) {
847
+ step ! ( env , [ _, _, index, array] => match env . force_lazy ( array) . as_ref( ) {
818
848
Value :: ArrayLit ( elems) => {
819
- let index = match ( index) . as_ref( ) {
849
+ let index = match env . force_lazy ( index) . as_ref( ) {
820
850
Value :: ConstLit ( Const :: U8 ( index, _) ) => Some ( usize :: from( * index) ) ,
821
851
Value :: ConstLit ( Const :: U16 ( index, _) ) => Some ( usize :: from( * index) ) ,
822
852
Value :: ConstLit ( Const :: U32 ( index, _) ) => usize :: try_from( * index) . ok( ) ,
823
853
Value :: ConstLit ( Const :: U64 ( index, _) ) => usize :: try_from( * index) . ok( ) ,
824
854
_ => return None ,
825
855
} ?;
826
- elems. get( index) . cloned ( ) ?
856
+ env . force_lazy ( elems. get( index) ? )
827
857
}
828
858
_ => return None ,
829
859
} )
0 commit comments