@@ -3,6 +3,7 @@ use std::sync::Arc;
33use fxhash:: FxHashMap ;
44use scoped_arena:: Scope ;
55
6+ use super :: semantics:: { LazyValue , LocalExprs } ;
67use crate :: core:: semantics:: { ArcValue , Elim , ElimEnv , Head , Value } ;
78use crate :: core:: { self , Const , Plicity , Prim , UIntStyle } ;
89use crate :: env:: { self , SharedEnv , UniqueEnv } ;
@@ -508,8 +509,8 @@ struct EnvBuilder<'arena> {
508509 entries : FxHashMap < Symbol , ( Prim , ArcValue < ' arena > ) > ,
509510 scope : & ' arena Scope < ' arena > ,
510511 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 > ,
513514}
514515
515516impl < ' arena > EnvBuilder < ' arena > {
@@ -577,13 +578,13 @@ macro_rules! step {
577578// TODO: Should we merge the spans of the param idents to produce the body span?
578579macro_rules! const_step {
579580 ( [ $( $param: ident : $Input: ident) ,* ] => $body: expr) => {
580- step!( _ , [ $( $param) ,* ] => match ( $( $param. as_ref( ) , ) * ) {
581+ step!( env , [ $( $param) ,* ] => match ( $( env . force_lazy ( $param) . as_ref( ) , ) * ) {
581582 ( $( Value :: ConstLit ( Const :: $Input( $param, ..) ) , ) * ) => Spanned :: empty( Arc :: new( Value :: ConstLit ( $body) ) ) ,
582583 _ => return None ,
583584 } )
584585 } ;
585586 ( [ $( $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( ) , ) * ) {
587588 ( $( Value :: ConstLit ( Const :: $Input( $param, $style) ) , ) * ) => Spanned :: empty( Arc :: new( Value :: ConstLit ( $body) ) ) ,
588589 _ => return None ,
589590 } )
@@ -611,21 +612,18 @@ pub fn repr(prim: Prim) -> Step {
611612 Prim :: FormatF32Le => step ! ( _, [ ] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: F32Type , [ ] ) ) ) ) ,
612613 Prim :: FormatF64Be => step ! ( _, [ ] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: F64Type , [ ] ) ) ) ) ,
613614 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) ) ) ,
625623 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 ) ) ,
627625 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 ) ) ,
629627 Prim :: ReportedError => step ! ( _, [ ] => Spanned :: empty( Arc :: new( Value :: prim( Prim :: ReportedError , [ ] ) ) ) ) ,
630628 _ => |_, _| None ,
631629 }
@@ -641,15 +639,49 @@ pub fn step(prim: Prim) -> Step {
641639 #[ allow( unreachable_code) ]
642640 Prim :: Absurd => step ! ( _, [ _, _] => panic!( "Constructed an element of `Void`" ) ) ,
643641
644- Prim :: FormatRepr => step ! ( env, [ format] => env. format_repr( format) ) ,
642+ Prim :: FormatRepr => step ! ( env, [ format] => env. format_repr( & env . force_lazy ( format) ) ) ,
645643
646644 Prim :: BoolEq => const_step ! ( [ x: Bool , y: Bool ] => Const :: Bool ( x == y) ) ,
647645 Prim :: BoolNeq => const_step ! ( [ x: Bool , y: Bool ] => Const :: Bool ( x != y) ) ,
648646 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) ) ,
651647 Prim :: BoolXor => const_step ! ( [ x: Bool , y: Bool ] => Const :: Bool ( * x ^ * y) ) ,
652648
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+
653685 Prim :: U8Eq => const_step ! ( [ x: U8 , y: U8 ] => Const :: Bool ( x == y) ) ,
654686 Prim :: U8Neq => const_step ! ( [ x: U8 , y: U8 ] => Const :: Bool ( x != y) ) ,
655687 Prim :: U8Gt => const_step ! ( [ x: U8 , y: U8 ] => Const :: Bool ( x > y) ) ,
@@ -775,22 +807,20 @@ pub fn step(prim: Prim) -> Step {
775807 Prim :: S64UAbs => const_step ! ( [ x: S64 ] => Const :: U64 ( i64 :: unsigned_abs( * x) , UIntStyle :: Decimal ) ) ,
776808
777809 Prim :: OptionFold => step ! ( env, [ _, _, on_none, on_some, option] => {
778- match option. match_prim_spine( ) ? {
810+ match env . force_lazy ( option) . match_prim_spine( ) ? {
779811 ( 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)
781813 } ,
782- ( Prim :: OptionNone , [ _] ) => on_none . clone ( ) ,
814+ ( Prim :: OptionNone , [ _] ) => env . force_lazy ( on_none ) ,
783815 _ => return None ,
784816 }
785817 } ) ,
786818
787819 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( ) {
789821 Value :: ArrayLit ( elems) => {
790822 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( ) {
794824 Value :: ConstLit ( Const :: Bool ( true ) ) => {
795825 return Some ( Spanned :: empty( Arc :: new( Value :: Stuck (
796826 Head :: Prim ( Prim :: OptionSome ) ,
@@ -814,16 +844,16 @@ pub fn step(prim: Prim) -> Step {
814844 }
815845
816846 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( ) {
818848 Value :: ArrayLit ( elems) => {
819- let index = match ( index) . as_ref( ) {
849+ let index = match env . force_lazy ( index) . as_ref( ) {
820850 Value :: ConstLit ( Const :: U8 ( index, _) ) => Some ( usize :: from( * index) ) ,
821851 Value :: ConstLit ( Const :: U16 ( index, _) ) => Some ( usize :: from( * index) ) ,
822852 Value :: ConstLit ( Const :: U32 ( index, _) ) => usize :: try_from( * index) . ok( ) ,
823853 Value :: ConstLit ( Const :: U64 ( index, _) ) => usize :: try_from( * index) . ok( ) ,
824854 _ => return None ,
825855 } ?;
826- elems. get( index) . cloned ( ) ?
856+ env . force_lazy ( elems. get( index) ? )
827857 }
828858 _ => return None ,
829859 } )
0 commit comments