2023-02-14 00:50:05 -05:00
use std ::fmt ;
2023-02-07 02:07:53 -05:00
use std ::rc ::Rc ;
2023-02-08 23:37:23 -05:00
use std ::convert ::From ;
2023-02-19 18:52:39 -05:00
use std ::collections ::{ BTreeSet , BTreeMap } ;
2023-02-14 00:50:05 -05:00
use std ::result ::Result ;
2023-02-18 19:32:59 -05:00
use std ::iter ;
2023-02-08 23:37:23 -05:00
2023-02-20 00:22:29 -05:00
// TODO:
// -extend vau & env logic and SuspendedPair PE with sequence_params & wrap_level
// -add veval and vif & -1 wrap_level handling to SuspendedPair
// -add current-hashes to if, DeriComb Calls, and DCtx-push/can_progress, and Hash to *everything*
// -expand combiner_Return_ok with (veval body {env}) and (func ...params) | func doesn't take de and func+params are return ok
// -add drop redundent veval
// -add compiler
2023-02-08 23:37:23 -05:00
impl From < i32 > for Form { fn from ( item : i32 ) -> Self { Form ::Int ( item ) } }
impl From < bool > for Form { fn from ( item : bool ) -> Self { Form ::Bool ( item ) } }
// todo, strings not symbols?
impl From < String > for Form { fn from ( item : String ) -> Self { Form ::Symbol ( item ) } }
impl From < & str > for Form { fn from ( item : & str ) -> Self { Form ::Symbol ( item . to_owned ( ) ) } }
impl < A : Into < Form > , B : Into < Form > > From < ( A , B ) > for Form {
fn from ( item : ( A , B ) ) -> Self {
Form ::Pair ( Rc ::new ( item . 0. into ( ) ) , Rc ::new ( item . 1. into ( ) ) )
}
}
2023-02-07 02:07:53 -05:00
2023-02-10 19:38:44 -05:00
pub enum PossibleTailCall {
Result ( Rc < Form > ) ,
TailCall ( Rc < Form > , Rc < Form > ) ,
}
2023-02-08 01:54:53 -05:00
#[ derive(Debug, Eq, PartialEq) ]
2023-02-07 02:07:53 -05:00
pub enum Form {
2023-02-08 01:54:53 -05:00
Nil ,
2023-02-07 02:07:53 -05:00
Int ( i32 ) ,
2023-02-08 01:54:53 -05:00
Bool ( bool ) ,
2023-02-07 02:07:53 -05:00
Symbol ( String ) ,
Pair ( Rc < Form > , Rc < Form > ) ,
2023-02-10 19:38:44 -05:00
PrimComb ( String , fn ( Rc < Form > , Rc < Form > ) -> PossibleTailCall ) ,
2023-02-14 00:50:05 -05:00
DeriComb { se : Rc < Form > , de : Option < String > , params : String , body : Rc < Form > } ,
2023-02-07 02:07:53 -05:00
}
impl Form {
2023-02-08 01:54:53 -05:00
pub fn truthy ( & self ) -> bool {
match self {
Form ::Bool ( b ) = > * b ,
Form ::Nil = > false ,
_ = > true ,
}
}
2023-02-07 02:07:53 -05:00
pub fn int ( & self ) -> Option < i32 > {
match self {
Form ::Int ( i ) = > Some ( * i ) ,
_ = > None ,
}
}
pub fn sym ( & self ) -> Option < & str > {
match self {
Form ::Symbol ( s ) = > Some ( s ) ,
_ = > None ,
}
}
pub fn car ( & self ) -> Option < Rc < Form > > {
match self {
2023-02-12 12:19:56 -05:00
Form ::Pair ( car , _cdr ) = > Some ( Rc ::clone ( car ) ) ,
2023-02-07 02:07:53 -05:00
_ = > None ,
}
}
pub fn cdr ( & self ) -> Option < Rc < Form > > {
match self {
2023-02-12 12:19:56 -05:00
Form ::Pair ( _car , cdr ) = > Some ( Rc ::clone ( cdr ) ) ,
2023-02-07 02:07:53 -05:00
_ = > None ,
}
}
2023-02-10 01:01:04 -05:00
pub fn append ( & self , x : Rc < Form > ) -> Option < Form > {
match self {
Form ::Pair ( car , cdr ) = > cdr . append ( x ) . map ( | x | Form ::Pair ( Rc ::clone ( car ) , Rc ::new ( x ) ) ) ,
Form ::Nil = > Some ( Form ::Pair ( x , Rc ::new ( Form ::Nil ) ) ) ,
_ = > None ,
}
}
2023-02-18 19:32:59 -05:00
2023-02-19 12:37:12 -05:00
pub fn marked ( & self , bctx : BCtx ) -> ( BCtx , Rc < MarkedForm > ) {
2023-02-18 19:32:59 -05:00
match & * self {
2023-02-19 12:37:12 -05:00
Form ::Nil = > ( bctx , Rc ::new ( MarkedForm ::Nil ) ) ,
Form ::Int ( i ) = > ( bctx , Rc ::new ( MarkedForm ::Int ( * i ) ) ) ,
Form ::Bool ( b ) = > ( bctx , Rc ::new ( MarkedForm ::Bool ( * b ) ) ) ,
Form ::Symbol ( s ) = > ( bctx , Rc ::new ( MarkedForm ::Symbol ( s . clone ( ) ) ) ) ,
2023-02-18 19:32:59 -05:00
Form ::Pair ( car , cdr ) = > {
2023-02-19 12:37:12 -05:00
let ( bctx , car ) = car . marked ( bctx ) ;
let ( bctx , cdr ) = cdr . marked ( bctx ) ;
( bctx , Rc ::new ( MarkedForm ::Pair ( NeededIds ::new_none ( ) , car , cdr ) ) )
2023-02-18 19:32:59 -05:00
} ,
Form ::DeriComb { se , de , params , body } = > {
2023-02-20 00:22:29 -05:00
// this is a bit sus, but we don't run into it as of yet
panic! ( ) ;
2023-02-19 12:37:12 -05:00
let ( bctx , se ) = se . marked ( bctx ) ;
let ( bctx , body ) = body . marked ( bctx ) ;
let ( bctx , new_id ) = bctx . new_id ( ) ;
( bctx , Rc ::new ( MarkedForm ::DeriComb { ids : NeededIds ::new_none ( ) , se , de : de . clone ( ) ,
2023-02-18 19:32:59 -05:00
id : new_id , wrap_level : 0 , sequence_params : vec ! [ ] ,
rest_params : Some ( params . clone ( ) ) , body } ) )
} ,
Form ::PrimComb ( name , _f ) = > {
2023-02-19 12:37:12 -05:00
( bctx , match & name [ .. ] {
2023-02-20 00:22:29 -05:00
" eval " = > Rc ::new ( MarkedForm ::PrimComb { name : " eval " . to_owned ( ) , takes_de : true , wrap_level : 1 , f : | bctx , dctx , p | {
// put in partial eval logic,
// and veval
2023-02-19 00:46:54 -05:00
let b = p . car ( ) ? . unval ( ) ? ;
2023-02-18 19:32:59 -05:00
let e = p . cdr ( ) ? . car ( ) ? ;
2023-02-19 00:46:54 -05:00
println! ( " Doing Eval (via tail call) of {} in {} " , b , e ) ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::TailCall ( e , b ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" vau " = > Rc ::new ( MarkedForm ::PrimComb { name : " vau " . to_owned ( ) , takes_de : true , wrap_level : 0 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let de = p . car ( ) ? . sym ( ) . map ( | s | s . to_owned ( ) ) . ok ( ) ;
let params = p . cdr ( ) ? . car ( ) ? . sym ( ) ? . to_owned ( ) ;
let body = p . cdr ( ) ? . cdr ( ) ? . car ( ) ? . unval ( ) ? ;
2023-02-19 12:37:12 -05:00
let se = Rc ::clone ( & dctx . e ) ;
let ( bctx , id ) = bctx . new_id ( ) ;
2023-02-19 01:18:59 -05:00
// TODO: figure out wrap level, sequence params, etc
2023-02-18 19:32:59 -05:00
let wrap_level = 0 ;
let sequence_params = vec! [ ] ;
let rest_params = Some ( params ) ;
2023-02-19 01:18:59 -05:00
//
2023-02-19 18:52:39 -05:00
let inner_dctx = dctx . copy_push_frame ( id . clone ( ) , & se , & de , None , & rest_params , None ) ;
let ( bctx , body ) = partial_eval ( bctx , inner_dctx , Rc ::clone ( & body ) ) ? ;
2023-02-19 01:18:59 -05:00
//
//
2023-02-19 20:33:09 -05:00
let ids = dctx . e . ids ( ) . union_without ( & body . ids ( ) , id . clone ( ) ) ;
println! ( " \t Union of {:?} and {:?} without {:?} is {:?} " , dctx . e . ids ( ) , body . ids ( ) , id , ids ) ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new (
2023-02-19 01:18:59 -05:00
MarkedForm ::DeriComb { ids , se , de , id , wrap_level , sequence_params , rest_params , body } ,
2023-02-18 19:32:59 -05:00
) ) ) )
} } ) ,
2023-02-20 00:22:29 -05:00
// TODO: handle vif, partial eval branches
" if " = > Rc ::new ( MarkedForm ::PrimComb { name : " if " . to_owned ( ) , takes_de : true , wrap_level : 0 , f : | bctx , dctx , p | {
2023-02-19 12:37:12 -05:00
let ( bctx , cond ) = partial_eval ( bctx , dctx . clone ( ) , p . car ( ) ? . unval ( ) ? ) ? ;
let e = Rc ::clone ( & dctx . e ) ;
2023-02-18 19:32:59 -05:00
if cond . truthy ( ) ? {
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::TailCall ( e , p . cdr ( ) ? . car ( ) ? . unval ( ) ? ) ) )
2023-02-18 19:32:59 -05:00
} else {
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::TailCall ( e , p . cdr ( ) ? . cdr ( ) ? . car ( ) ? . unval ( ) ? ) ) )
2023-02-18 19:32:59 -05:00
}
} } ) ,
// TODO: handle these in the context of paritals
2023-02-20 00:22:29 -05:00
" cons " = > Rc ::new ( MarkedForm ::PrimComb { name : " cons " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let h = p . car ( ) ? ;
let t = p . cdr ( ) ? . car ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Pair ( h . ids ( ) . union ( & t . ids ( ) ) , h , t ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" car " = > Rc ::new ( MarkedForm ::PrimComb { name : " car " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( p . car ( ) ? . car ( ) ? ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" cdr " = > Rc ::new ( MarkedForm ::PrimComb { name : " cdr " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( p . car ( ) ? . cdr ( ) ? ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" quote " = > Rc ::new ( MarkedForm ::PrimComb { name : " quote " . to_owned ( ) , takes_de : false , wrap_level : 0 , f : | bctx , dctx , p | {
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( p . car ( ) ? ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
// This one needs to control eval to print debug before continuint
// which is werid to PE
2023-02-20 00:22:29 -05:00
" debug " = > Rc ::new ( MarkedForm ::PrimComb { name : " debug " . to_owned ( ) , takes_de : true , wrap_level : 0 , f : | bctx , dctx , p | {
panic! ( ) ;
2023-02-19 12:37:12 -05:00
let e = Rc ::clone ( & dctx . e ) ;
Ok ( ( bctx , PossibleMarkedTailCall ::TailCall ( e , p . cdr ( ) ? . car ( ) ? ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
// ditto
2023-02-20 00:22:29 -05:00
" assert " = > Rc ::new ( MarkedForm ::PrimComb { name : " assert " . to_owned ( ) , takes_de : true , wrap_level : 0 , f : | bctx , dctx , p | {
panic! ( ) ;
let ( bctx , cond ) = partial_eval ( bctx , dctx . clone ( ) , p . car ( ) ? . unval ( ) ? ) ? ;
2023-02-18 19:32:59 -05:00
if ! cond . truthy ( ) ? {
println! ( " Assert failed: {:?} " , cond ) ;
}
assert! ( cond . truthy ( ) ? ) ;
2023-02-19 12:37:12 -05:00
let e = Rc ::clone ( & dctx . e ) ;
Ok ( ( bctx , PossibleMarkedTailCall ::TailCall ( e , p . cdr ( ) ? . car ( ) ? ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
// (vau de params body), should be able to take in wrap_level != 1 and do stuff
2023-02-20 00:22:29 -05:00
" = " = > Rc ::new ( MarkedForm ::PrimComb { name : " = " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? ;
2023-02-19 00:46:54 -05:00
println! ( " DOing (= {} {} ) = {} " , a , b , a = = b ) ;
2023-02-18 19:32:59 -05:00
// TODO: double check that this ignores ids etc. It should, since
// wrap_level=1 should mean that everything's a value
// also, it should just check by hash then?
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Bool ( a = = b ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" < " = > Rc ::new ( MarkedForm ::PrimComb { name : " < " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Bool ( a . int ( ) ? < b . int ( ) ? ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" > " = > Rc ::new ( MarkedForm ::PrimComb { name : " > " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Bool ( a . int ( ) ? > b . int ( ) ? ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" <= " = > Rc ::new ( MarkedForm ::PrimComb { name : " <= " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Bool ( a . int ( ) ? < = b . int ( ) ? ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" >= " = > Rc ::new ( MarkedForm ::PrimComb { name : " >= " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Bool ( a . int ( ) ? > = b . int ( ) ? ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" + " = > Rc ::new ( MarkedForm ::PrimComb { name : " + " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? . int ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? . int ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Int ( a + b ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" - " = > Rc ::new ( MarkedForm ::PrimComb { name : " - " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? . int ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? . int ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Int ( a - b ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" * " = > Rc ::new ( MarkedForm ::PrimComb { name : " * " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? . int ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? . int ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Int ( a * b ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" / " = > Rc ::new ( MarkedForm ::PrimComb { name : " / " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? . int ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? . int ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Int ( a / b ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" % " = > Rc ::new ( MarkedForm ::PrimComb { name : " % " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? . int ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? . int ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Int ( a % b ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" & " = > Rc ::new ( MarkedForm ::PrimComb { name : " & " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? . int ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? . int ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Int ( a & b ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" | " = > Rc ::new ( MarkedForm ::PrimComb { name : " | " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? . int ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? . int ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Int ( a | b ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" ^ " = > Rc ::new ( MarkedForm ::PrimComb { name : " ^ " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-18 19:32:59 -05:00
let a = p . car ( ) ? . int ( ) ? ;
let b = p . cdr ( ) ? . car ( ) ? . int ( ) ? ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Int ( a ^ b ) ) ) ) )
2023-02-18 19:32:59 -05:00
} } ) ,
2023-02-20 00:22:29 -05:00
" comb? " = > Rc ::new ( MarkedForm ::PrimComb { name : " comb? " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Bool ( match & * p . car ( ) ? {
2023-02-18 19:32:59 -05:00
MarkedForm ::PrimComb { .. } = > true ,
MarkedForm ::DeriComb { .. } = > true ,
_ = > false ,
} ) ) ) ) )
} } ) ,
2023-02-20 00:22:29 -05:00
" pair? " = > Rc ::new ( MarkedForm ::PrimComb { name : " pair? " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Bool ( match & * p . car ( ) ? {
2023-02-18 19:32:59 -05:00
MarkedForm ::Pair ( _i , _a , _b ) = > true ,
_ = > false ,
} ) ) ) ) )
} } ) ,
2023-02-20 00:22:29 -05:00
" symbol? " = > Rc ::new ( MarkedForm ::PrimComb { name : " symbol? " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Bool ( match & * p . car ( ) ? {
2023-02-18 19:32:59 -05:00
MarkedForm ::Symbol ( _ ) = > true ,
_ = > false ,
} ) ) ) ) )
} } ) ,
2023-02-20 00:22:29 -05:00
" int? " = > Rc ::new ( MarkedForm ::PrimComb { name : " int? " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Bool ( match & * p . car ( ) ? {
2023-02-18 19:32:59 -05:00
MarkedForm ::Int ( _ ) = > true ,
_ = > false ,
} ) ) ) ) )
} } ) ,
// maybe bool? but also could be derived. Nil def
2023-02-20 00:22:29 -05:00
" bool? " = > Rc ::new ( MarkedForm ::PrimComb { name : " bool? " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Bool ( match & * p . car ( ) ? {
2023-02-18 19:32:59 -05:00
MarkedForm ::Bool ( _ ) = > true ,
_ = > false ,
} ) ) ) ) )
} } ) ,
2023-02-20 00:22:29 -05:00
" nil? " = > Rc ::new ( MarkedForm ::PrimComb { name : " nil? " . to_owned ( ) , takes_de : false , wrap_level : 1 , f : | bctx , dctx , p | {
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , PossibleMarkedTailCall ::Result ( Rc ::new ( MarkedForm ::Bool ( match & * p . car ( ) ? {
2023-02-18 19:32:59 -05:00
MarkedForm ::Nil = > true ,
_ = > false ,
} ) ) ) ) )
} } ) ,
_ = > panic! ( " gah! don't have partial eval version of {} " , name ) ,
} )
} ,
}
}
2023-02-07 02:07:53 -05:00
}
2023-02-14 00:50:05 -05:00
impl fmt ::Display for Form {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
match self {
Form ::Nil = > write! ( f , " nil " ) ,
Form ::Int ( i ) = > write! ( f , " {} " , i ) ,
Form ::Bool ( b ) = > write! ( f , " {} " , b ) ,
Form ::Symbol ( s ) = > write! ( f , " {} " , s ) ,
Form ::Pair ( car , cdr ) = > {
write! ( f , " ({} " , car ) ? ;
let mut traverse : Rc < Form > = Rc ::clone ( cdr ) ;
loop {
match & * traverse {
Form ::Pair ( ref carp , ref cdrp ) = > {
write! ( f , " {} " , carp ) ? ;
traverse = Rc ::clone ( cdrp ) ;
} ,
Form ::Nil = > {
write! ( f , " ) " ) ? ;
return Ok ( ( ) ) ;
} ,
x = > {
write! ( f , " . {}) " , x ) ? ;
return Ok ( ( ) ) ;
} ,
}
}
} ,
Form ::PrimComb ( name , _f ) = > write! ( f , " <{}> " , name ) ,
Form ::DeriComb { se , de , params , body } = > {
write! ( f , " <{} {} {}> " , de . as_ref ( ) . unwrap_or ( & " " . to_string ( ) ) , params , body )
} ,
}
}
}
2023-02-16 18:21:13 -05:00
#[ derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd) ]
pub struct EnvID ( i32 ) ;
2023-02-18 19:32:59 -05:00
#[ derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd) ]
pub struct Hash ( u64 ) ;
2023-02-16 18:21:13 -05:00
2023-02-14 00:50:05 -05:00
#[ derive(Debug, Clone, Eq, PartialEq) ]
pub enum NeededIds {
2023-02-18 19:32:59 -05:00
True ( BTreeSet < Hash > ) ,
None ( BTreeSet < Hash > ) ,
Some ( BTreeSet < EnvID > , BTreeSet < Hash > ) ,
2023-02-14 00:50:05 -05:00
}
impl NeededIds {
2023-02-18 19:32:59 -05:00
fn new_true ( ) -> Self { NeededIds ::True ( BTreeSet ::new ( ) ) }
fn new_none ( ) -> Self { NeededIds ::None ( BTreeSet ::new ( ) ) }
fn new_single ( i : EnvID ) -> Self { NeededIds ::Some ( iter ::once ( i ) . collect ( ) , BTreeSet ::new ( ) ) }
2023-02-19 23:16:10 -05:00
fn needs_nothing ( & self ) -> bool {
match self {
NeededIds ::True ( hashes ) = > false ,
NeededIds ::None ( hashes ) = > hashes . is_empty ( ) ,
NeededIds ::Some ( set , hashes ) = > false ,
}
}
2023-02-18 19:32:59 -05:00
fn hashes ( & self ) -> & BTreeSet < Hash > {
match self {
NeededIds ::True ( hashes ) = > hashes ,
NeededIds ::None ( hashes ) = > hashes ,
NeededIds ::Some ( set , hashes ) = > hashes ,
}
}
2023-02-14 00:50:05 -05:00
fn union ( & self , other : & NeededIds ) -> Self {
match self {
2023-02-18 19:32:59 -05:00
NeededIds ::True ( hashes ) = > NeededIds ::True ( hashes . union ( other . hashes ( ) ) . cloned ( ) . collect ( ) ) ,
NeededIds ::None ( hashes ) = > other . union_hashes ( hashes ) ,
NeededIds ::Some ( set , hashes ) = > match other {
NeededIds ::True ( ohashes ) = > NeededIds ::True ( hashes . union ( ohashes ) . cloned ( ) . collect ( ) ) ,
NeededIds ::None ( ohashes ) = > NeededIds ::Some ( set . clone ( ) , hashes . union ( ohashes ) . cloned ( ) . collect ( ) ) ,
NeededIds ::Some ( oset , ohashes ) = > NeededIds ::Some ( set . union ( oset ) . cloned ( ) . collect ( ) , hashes . union ( ohashes ) . cloned ( ) . collect ( ) ) ,
2023-02-14 00:50:05 -05:00
} ,
}
}
2023-02-19 20:33:09 -05:00
fn union_without ( & self , other : & NeededIds , without : EnvID ) -> Self {
2023-02-19 23:16:10 -05:00
self . union ( other ) . without ( without )
2023-02-19 20:33:09 -05:00
}
fn without ( self , without : EnvID ) -> Self {
match self {
NeededIds ::True ( _ ) = > self ,
NeededIds ::None ( _ ) = > self ,
2023-02-19 23:16:10 -05:00
NeededIds ::Some ( set , hashes ) = > {
let new : BTreeSet < EnvID > = set . into_iter ( ) . filter ( | x | * x ! = without ) . collect ( ) ;
if new . is_empty ( ) {
NeededIds ::None ( hashes )
} else {
NeededIds ::Some ( new , hashes )
}
} ,
2023-02-19 20:33:09 -05:00
}
}
2023-02-18 19:32:59 -05:00
fn union_hashes ( & self , other : & BTreeSet < Hash > ) -> Self {
match self {
NeededIds ::True ( hashes ) = > NeededIds ::True ( other . union ( hashes ) . cloned ( ) . collect ( ) ) ,
NeededIds ::None ( hashes ) = > NeededIds ::None ( other . union ( hashes ) . cloned ( ) . collect ( ) ) ,
NeededIds ::Some ( set , hashes ) = > NeededIds ::Some ( set . clone ( ) , other . union ( hashes ) . cloned ( ) . collect ( ) ) ,
}
}
fn add_hash ( & self , h : Hash ) -> Self {
match self {
NeededIds ::True ( hashes ) = > NeededIds ::True ( hashes . iter ( ) . cloned ( ) . chain ( iter ::once ( h ) ) . collect ( ) ) ,
NeededIds ::None ( hashes ) = > NeededIds ::None ( hashes . iter ( ) . cloned ( ) . chain ( iter ::once ( h ) ) . collect ( ) ) ,
NeededIds ::Some ( set , hashes ) = > NeededIds ::Some ( set . clone ( ) , hashes . iter ( ) . cloned ( ) . chain ( iter ::once ( h ) ) . collect ( ) ) ,
}
}
fn add_id ( & self , i : EnvID ) -> Self {
match self {
NeededIds ::True ( hashes ) = > NeededIds ::True ( hashes . clone ( ) ) ,
NeededIds ::None ( hashes ) = > NeededIds ::Some ( iter ::once ( i ) . collect ( ) , hashes . clone ( ) ) ,
NeededIds ::Some ( set , hashes ) = > NeededIds ::Some ( set . iter ( ) . cloned ( ) . chain ( iter ::once ( i ) ) . collect ( ) , hashes . clone ( ) ) ,
}
}
2023-02-14 00:50:05 -05:00
}
pub enum PossibleMarkedTailCall {
Result ( Rc < MarkedForm > ) ,
TailCall ( Rc < MarkedForm > , Rc < MarkedForm > ) ,
}
2023-02-19 12:37:12 -05:00
2023-02-18 22:46:23 -05:00
#[ derive(Clone) ]
2023-02-19 12:37:12 -05:00
pub struct BCtx {
2023-02-18 19:32:59 -05:00
id_counter : i32
}
2023-02-19 12:37:12 -05:00
impl BCtx {
2023-02-18 19:32:59 -05:00
pub fn new_id ( mut self ) -> ( Self , EnvID ) {
let new_id = EnvID ( self . id_counter ) ;
self . id_counter + = 1 ;
( self , new_id )
}
2023-02-16 18:21:13 -05:00
}
2023-02-19 12:37:12 -05:00
2023-02-19 18:52:39 -05:00
// force is for drop_redundent_eval
2023-02-20 00:22:29 -05:00
// memo is only for recording currently executing hashes (calls and if's, current for us)
2023-02-19 18:52:39 -05:00
// only_head is not currently used
//only_head env env_counter memo env_stack force
2023-02-19 12:37:12 -05:00
#[ derive(Clone) ]
pub struct DCtx {
e : Rc < MarkedForm > ,
2023-02-19 18:52:39 -05:00
sus_env_stack : Rc < BTreeMap < EnvID , Rc < MarkedForm > > > ,
sus_prm_stack : Rc < BTreeMap < EnvID , Rc < MarkedForm > > > ,
2023-02-19 19:28:48 -05:00
real_set : Rc < BTreeSet < EnvID > > ,
force : bool ,
current : Rc < BTreeSet < Hash > > ,
2023-02-19 23:16:10 -05:00
ident : usize ,
2023-02-19 12:37:12 -05:00
}
impl DCtx {
2023-02-19 18:52:39 -05:00
pub fn copy_set_env ( & self , e : & Rc < MarkedForm > ) -> Self {
2023-02-19 23:16:10 -05:00
DCtx { e : Rc ::clone ( e ) , sus_env_stack : Rc ::clone ( & self . sus_env_stack ) , sus_prm_stack : Rc ::clone ( & self . sus_prm_stack ) , real_set : Rc ::clone ( & self . real_set ) , force : self . force , current : Rc ::clone ( & self . current ) , ident : self . ident + 1 }
2023-02-19 18:52:39 -05:00
}
pub fn copy_push_frame ( & self , id : EnvID , se : & Rc < MarkedForm > , de : & Option < String > , e : Option < Rc < MarkedForm > > , rest_params : & Option < String > , prms : Option < Rc < MarkedForm > > ) -> Self {
let mut sus_env_stack = Rc ::clone ( & self . sus_env_stack ) ;
let mut sus_prm_stack = Rc ::clone ( & self . sus_prm_stack ) ;
2023-02-19 19:28:48 -05:00
let mut real_set = Rc ::clone ( & self . real_set ) ;
if ( e . is_some ( ) | | prms . is_some ( ) ) {
Rc ::make_mut ( & mut real_set ) . insert ( id . clone ( ) ) ;
}
2023-02-19 18:52:39 -05:00
let inner_env = if let Some ( de ) = de {
let de_val = if let Some ( e ) = e {
Rc ::make_mut ( & mut sus_env_stack ) . insert ( id . clone ( ) , Rc ::clone ( & e ) ) ;
e
} else {
Rc ::new ( MarkedForm ::SuspendedEnvLookup { name : Some ( de . clone ( ) ) , id : id . clone ( ) } )
} ;
massoc ( de , de_val , Rc ::clone ( se ) )
} else { Rc ::clone ( se ) } ;
// not yet supporting sequence params
let inner_env = if let Some ( p ) = rest_params {
let p_val = if let Some ( prms ) = prms {
Rc ::make_mut ( & mut sus_prm_stack ) . insert ( id . clone ( ) , Rc ::clone ( & prms ) ) ;
prms
} else {
Rc ::new ( MarkedForm ::SuspendedParamLookup { name : Some ( p . clone ( ) ) , id : id . clone ( ) , cdr_num : 0 , car : false } )
} ;
massoc ( p , p_val , inner_env )
} else { inner_env } ;
2023-02-19 19:28:48 -05:00
// Push on current frame hash?!
let new_current = Rc ::clone ( & self . current ) ;
2023-02-19 23:16:10 -05:00
DCtx { e : inner_env , sus_env_stack , sus_prm_stack , real_set , force : self . force , current : new_current , ident : self . ident + 1 }
2023-02-19 19:28:48 -05:00
}
pub fn can_progress ( & self , ids : NeededIds ) -> bool {
// check if ids is true || ids intersection EnvIDs in our stacks is non empty || ids.hashes - current is non empty
match ids {
NeededIds ::True ( hashes ) = > true ,
NeededIds ::None ( hashes ) = > ! self . current . is_superset ( & hashes ) ,
NeededIds ::Some ( ids , hashes ) = > ( ! self . real_set . is_disjoint ( & ids ) ) | | ( ! self . current . is_superset ( & hashes ) ) ,
}
2023-02-16 18:21:13 -05:00
}
}
2023-02-19 12:37:12 -05:00
pub fn new_base_ctxs ( ) -> ( BCtx , DCtx ) {
let bctx = BCtx { id_counter : 0 } ;
let ( bctx , root_env ) = root_env ( ) . marked ( bctx ) ;
2023-02-19 23:16:10 -05:00
( bctx , DCtx { e : root_env , sus_env_stack : Rc ::new ( BTreeMap ::new ( ) ) , sus_prm_stack : Rc ::new ( BTreeMap ::new ( ) ) , real_set : Rc ::new ( BTreeSet ::new ( ) ) , force : false , current : Rc ::new ( BTreeSet ::new ( ) ) , ident : 0 } )
2023-02-19 12:37:12 -05:00
}
2023-02-19 20:33:09 -05:00
pub fn combiner_return_ok ( x : Rc < MarkedForm > , check_id : EnvID ) -> bool {
match match & * x {
MarkedForm ::Nil = > return true ,
MarkedForm ::Int ( _ ) = > return true ,
MarkedForm ::Bool ( _ ) = > return true ,
MarkedForm ::Symbol ( _ ) = > return true ,
MarkedForm ::Pair ( ids , _ , _ ) = > ids ,
MarkedForm ::SuspendedSymbol ( _ ) = > return false ,
MarkedForm ::SuspendedParamLookup { id , .. } = > return * id ! = check_id ,
MarkedForm ::SuspendedEnvLookup { id , .. } = > return * id ! = check_id ,
MarkedForm ::SuspendedPair { ids , attempted , car , cdr } = > {
// expand with (veval body {env}) and (func ...params) | func doesn't take de and func+params are return ok
return false
} ,
MarkedForm ::PrimComb { .. } = > return true ,
MarkedForm ::DeriComb { ids , .. } = > ids ,
} {
NeededIds ::True ( _hashes ) = > false ,
NeededIds ::None ( _hashes ) = > true ,
NeededIds ::Some ( ids , _hashes ) = > ! ids . contains ( & check_id ) ,
}
//; Handles let 4.3 through macro level leaving it as (<comb wraplevel=1 (y) (+ y x 12)> 13)
//; need handling of symbols (which is illegal for eval but ok for calls) to push it farther
//(combiner_return_ok (rec-lambda combiner_return_ok (func_result env_id)
// (cond ((not (later_head? func_result)) (not (check_for_env_id_in_result env_id func_result)))
// ; special cases now
// ; *(veval body {env}) => (combiner_return_ok {env})
// ; The reason we don't have to check body is that this form is only creatable in ways that body was origionally a value and only need {env}
// ; Either it's created by eval, in which case it's fine, or it's created by something like (eval (array veval x de) de2) and the array has checked it,
// ; or it's created via literal vau invocation, in which case the body is a value.
// ((and (marked_array? func_result)
// (prim_comb? (idx (.marked_array_values func_result) 0))
// (= 'veval (.prim_comb_sym (idx (.marked_array_values func_result) 0)))
// (= 3 (len (.marked_array_values func_result)))
// (combiner_return_ok (idx (.marked_array_values func_result) 2) env_id)) true)
// ; (func ...params) => (and (doesn't take de func) (foldl combiner_return_ok (cons func params)))
// ;
// ((and (marked_array? func_result)
// (not (comb_takes_de? (idx (.marked_array_values func_result) 0) (len (.marked_array_values func_result))))
// (foldl (lambda (a x) (and a (combiner_return_ok x env_id))) true (.marked_array_values func_result))) true)
// ; So that's enough for macro like, but we would like to take it farther
// ; For like (let1 a 12 (wrap (vau (x) (let1 y (+ a 1) (+ y x a)))))
// ; we get to (+ 13 x 12) not being a value, and it reconstructs
// ; (<comb wraplevel=1 (y) (+ y x 12)> 13)
// ; and that's what eval gets, and eval then gives up as well.
// ; That will get caught by the above cases to remain the expansion (<comb wraplevel=1 (y) (+ y x 12)> 13),
// ; but ideally we really want another case to allow (+ 13 x 12) to bubble up
// ; I think it would be covered by the (func ...params) case if a case is added to allow symbols to be bubbled up if their
// ; needed for progress wasn't true or the current environment, BUT this doesn't work for eval, just for functions,
// ; since eval changes the entire env chain (but that goes back to case 1, and might be eliminated at compile if it's an env reachable from the func).
// ;
// ;
// ; Do note a key thing to be avoided is allowing any non-val inside a comb, since that can cause a fake env's ID to
// ; reference the wrong env/comb in the chain.
// ; We do allow calling eval with a fake env, but since it's only callable withbody value and is strict (by calling this)
// ; about it's return conditions, and the env it's called with must be ok in the chain, and eval doesn't introduce a new scope, it works ok.
// ; We do have to be careful about allowing returned later symbols from it though, since it could be an entirely different env chain.
// (true false)
// )
//))
}
2023-02-19 12:37:12 -05:00
pub fn partial_eval ( bctx : BCtx , dctx : DCtx , x : Rc < MarkedForm > ) -> Result < ( BCtx , Rc < MarkedForm > ) , String > {
2023-02-19 23:16:10 -05:00
println! ( " {:ident$} PE: {} " , " " , x , ident = dctx . ident * 4 ) ;
2023-02-19 19:28:48 -05:00
let should_go = dctx . force | | dctx . can_progress ( x . ids ( ) ) ;
if ! should_go {
2023-02-20 00:22:29 -05:00
println! ( " {:ident$} Shouldn't go! " , " " , ident = dctx . ident * 4 ) ;
2023-02-19 19:28:48 -05:00
return Ok ( ( bctx , x ) ) ;
}
2023-02-16 18:21:13 -05:00
match & * x {
2023-02-18 19:32:59 -05:00
MarkedForm ::SuspendedSymbol ( name ) = > {
2023-02-19 12:37:12 -05:00
let mut t = Rc ::clone ( & dctx . e ) ;
2023-02-18 19:32:59 -05:00
while name ! = t . car ( ) ? . car ( ) ? . sym ( ) ? {
t = t . cdr ( ) ? ;
2023-02-16 18:21:13 -05:00
}
2023-02-19 12:37:12 -05:00
return Ok ( ( bctx , t . car ( ) ? . cdr ( ) ? ) ) ;
2023-02-18 19:32:59 -05:00
} ,
2023-02-20 00:22:29 -05:00
MarkedForm ::SuspendedEnvLookup { name , id } = > {
2023-02-19 18:52:39 -05:00
if let Some ( v ) = dctx . sus_env_stack . get ( id ) {
Ok ( ( bctx , Rc ::clone ( v ) ) )
} else {
Ok ( ( bctx , x ) )
}
2023-02-19 01:18:59 -05:00
} ,
2023-02-20 00:22:29 -05:00
MarkedForm ::SuspendedParamLookup { name , id , cdr_num , car } = > {
2023-02-19 18:52:39 -05:00
if let Some ( v ) = dctx . sus_prm_stack . get ( id ) {
Ok ( ( bctx , Rc ::clone ( v ) ) )
} else {
Ok ( ( bctx , x ) )
}
2023-02-16 18:21:13 -05:00
} ,
2023-02-18 19:32:59 -05:00
MarkedForm ::SuspendedPair { ids , attempted , car , cdr } = > {
2023-02-19 12:37:12 -05:00
let ( bctx , mut car ) = partial_eval ( bctx , dctx . clone ( ) , Rc ::clone ( car ) ) ? ;
let ( mut bctx , mut cdr ) = partial_eval ( bctx , dctx . clone ( ) , Rc ::clone ( cdr ) ) ? ;
2023-02-20 00:22:29 -05:00
let mut new_attempted = attempted . clone ( ) ;
2023-02-18 22:46:23 -05:00
while let Some ( wrap_level ) = car . wrap_level ( ) {
if wrap_level > 0 {
2023-02-19 12:37:12 -05:00
fn map_unval_peval ( bctx : BCtx , dctx : DCtx , x : Rc < MarkedForm > ) -> Result < ( BCtx , Rc < MarkedForm > ) , String > {
2023-02-18 22:46:23 -05:00
match & * x {
MarkedForm ::Pair ( ids , x_car , x_cdr ) = > {
2023-02-19 12:37:12 -05:00
let ( bctx , new_x_car ) = partial_eval ( bctx , dctx . clone ( ) , x_car . unval ( ) ? ) ? ;
let ( bctx , new_x_cdr ) = map_unval_peval ( bctx , dctx . clone ( ) , Rc ::clone ( x_cdr ) ) ? ;
return Ok ( ( bctx , Rc ::new ( MarkedForm ::Pair ( new_x_car . ids ( ) . union ( & new_x_cdr . ids ( ) ) , new_x_car , new_x_cdr ) ) ) ) ;
2023-02-18 22:46:23 -05:00
} ,
2023-02-19 12:37:12 -05:00
MarkedForm ::Nil = > return Ok ( ( bctx , x ) ) ,
2023-02-18 22:46:23 -05:00
_ = > return Err ( " not a list " . to_owned ( ) ) ,
}
}
2023-02-19 12:37:12 -05:00
if let Ok ( ( new_bctx , new_cdr ) ) = map_unval_peval ( bctx . clone ( ) , dctx . clone ( ) , Rc ::clone ( & cdr ) ) {
2023-02-18 22:46:23 -05:00
car = car . decrement_wrap_level ( ) . unwrap ( ) ;
cdr = new_cdr ;
2023-02-19 12:37:12 -05:00
bctx = new_bctx ;
2023-02-18 22:46:23 -05:00
} else {
break ;
}
} else {
// check to see if can do call
2023-02-20 00:22:29 -05:00
// not pure values are fine for -1 wraps, which we need to add? veval and vif?
2023-02-19 00:46:54 -05:00
if ! cdr . is_value ( ) {
break ;
}
2023-02-19 20:33:09 -05:00
match & * car {
2023-02-20 00:22:29 -05:00
MarkedForm ::PrimComb { name , takes_de , wrap_level , f } = > {
new_attempted = Attempted ::True ( if * takes_de { Some ( dctx . e . ids ( ) ) } else { None } ) ;
2023-02-19 20:33:09 -05:00
if let Ok ( ( bctx , r ) ) = f ( bctx . clone ( ) , dctx . clone ( ) , Rc ::clone ( & cdr ) ) {
match r {
PossibleMarkedTailCall ::Result ( result ) = > return Ok ( ( bctx , result ) ) ,
// Sigh, no tail-callin right now
PossibleMarkedTailCall ::TailCall ( new_env , next ) = > {
println! ( " Doing tail call of {} in {} " , next , new_env ) ;
if let Ok ( ( new_bctx , res ) ) = partial_eval ( bctx . clone ( ) , dctx . copy_set_env ( & new_env ) , Rc ::clone ( & next ) ) {
println! ( " Doing tail call result is {} " , res ) ;
return Ok ( ( new_bctx , res ) ) ;
} else {
println! ( " Tail call failed " ) ;
if new_env = = dctx . e {
return Ok ( ( bctx , next ) ) ;
} else {
// maybe this should enplace the TailCall with an eval
break ; // break out to reconstruction
}
}
}
}
} else { break ; }
}
2023-02-19 00:46:54 -05:00
MarkedForm ::DeriComb { ids , se , de , id , wrap_level , sequence_params , rest_params , body } = > {
2023-02-20 00:22:29 -05:00
new_attempted = Attempted ::True ( if de . is_some ( ) { Some ( dctx . e . ids ( ) ) } else { None } ) ;
2023-02-19 00:46:54 -05:00
// not yet supporting sequence params
2023-02-19 20:33:09 -05:00
// needs to check hash
2023-02-19 23:16:10 -05:00
let inner_dctx = dctx . copy_push_frame ( id . clone ( ) , & se , & de , Some ( Rc ::clone ( & dctx . e ) ) , & rest_params , Some ( Rc ::clone ( & cdr ) ) ) ;
2023-02-19 00:46:54 -05:00
// check for id in it?
2023-02-19 20:33:09 -05:00
// needs to check return OK
2023-02-19 23:16:10 -05:00
println! ( " {:ident$} doing a call eval of {} in {} " , " " , body , inner_dctx . e , ident = inner_dctx . ident * 4 ) ;
if let Ok ( ( bctx , r ) ) = partial_eval ( bctx . clone ( ) , inner_dctx , Rc ::clone ( body ) ) {
2023-02-19 20:33:09 -05:00
if combiner_return_ok ( Rc ::clone ( & r ) , id . clone ( ) ) {
return Ok ( ( bctx , r ) ) ;
2023-02-18 22:46:23 -05:00
}
}
2023-02-19 20:33:09 -05:00
break ; // failed call for one reason or the other
} ,
_ = > break ,
2023-02-18 22:46:23 -05:00
}
}
}
2023-02-16 18:21:13 -05:00
// update IDs
2023-02-18 19:32:59 -05:00
let new_ids = car . ids ( ) . union ( & cdr . ids ( ) ) ;
2023-02-20 00:22:29 -05:00
let new_ids = match new_ids {
NeededIds ::True ( _ ) = > new_ids ,
NeededIds ::None ( hashes ) = > match & new_attempted {
Attempted ::False = > NeededIds ::True ( hashes ) ,
Attempted ::True ( Some ( oids ) ) = > oids . union_hashes ( & hashes ) ,
Attempted ::True ( None ) = > NeededIds ::None ( hashes ) ,
} ,
NeededIds ::Some ( _ , _ ) = > new_ids ,
} ;
2023-02-19 12:37:12 -05:00
Ok ( ( bctx , Rc ::new ( MarkedForm ::SuspendedPair { ids : new_ids , attempted : new_attempted , car , cdr } ) ) )
2023-02-18 19:32:59 -05:00
} ,
MarkedForm ::Pair ( ids , car , cdr ) = > {
2023-02-19 12:37:12 -05:00
let ( bctx , car ) = partial_eval ( bctx , dctx . clone ( ) , Rc ::clone ( car ) ) ? ;
let ( bctx , cdr ) = partial_eval ( bctx , dctx , Rc ::clone ( cdr ) ) ? ;
2023-02-19 20:33:09 -05:00
Ok ( ( bctx , Rc ::new ( MarkedForm ::Pair ( car . ids ( ) . union ( & cdr . ids ( ) ) , car , cdr ) ) ) )
2023-02-16 18:21:13 -05:00
} ,
2023-02-19 23:16:10 -05:00
MarkedForm ::DeriComb { ids , se , de , id , wrap_level , sequence_params , rest_params , body } = > {
if ! se . ids ( ) . needs_nothing ( ) {
// the current env is our new se
let se = Rc ::clone ( & dctx . e ) ;
let inner_dctx = dctx . copy_push_frame ( id . clone ( ) , & se , & de , None , & rest_params , None ) ;
let ( bctx , body ) = partial_eval ( bctx , inner_dctx , Rc ::clone ( & body ) ) ? ;
//
//
let ids = dctx . e . ids ( ) . union_without ( & body . ids ( ) , id . clone ( ) ) ;
println! ( " \t Union of {:?} and {:?} without {:?} is {:?} " , dctx . e . ids ( ) , body . ids ( ) , id , ids ) ;
Ok ( ( bctx , Rc ::new ( MarkedForm ::DeriComb { ids : ids . clone ( ) , se , de : de . clone ( ) , id : id . clone ( ) , wrap_level : * wrap_level , sequence_params : sequence_params . clone ( ) , rest_params : rest_params . clone ( ) , body } ) ) )
} else {
Ok ( ( bctx , x ) )
}
} ,
MarkedForm ::PrimComb { .. } = > Ok ( ( bctx , x ) ) ,
2023-02-19 12:37:12 -05:00
_ = > Ok ( ( bctx , x ) ) ,
2023-02-16 18:21:13 -05:00
}
}
2023-02-14 00:50:05 -05:00
#[ derive(Debug, Clone, Eq, PartialEq) ]
2023-02-18 19:32:59 -05:00
pub enum Attempted {
2023-02-20 00:22:29 -05:00
True ( Option < NeededIds > ) ,
2023-02-18 19:32:59 -05:00
False ,
}
#[ derive(Debug, Clone, Eq, PartialEq) ]
2023-02-14 00:50:05 -05:00
pub enum MarkedForm {
2023-02-18 19:32:59 -05:00
Nil ,
Int ( i32 ) ,
Bool ( bool ) ,
Symbol ( String ) ,
Pair ( NeededIds , Rc < MarkedForm > , Rc < MarkedForm > ) ,
2023-02-07 02:07:53 -05:00
2023-02-18 19:32:59 -05:00
SuspendedSymbol ( String ) ,
2023-02-19 01:18:59 -05:00
SuspendedParamLookup { name : Option < String > , id : EnvID , cdr_num : i32 , car : bool } ,
SuspendedEnvLookup { name : Option < String > , id : EnvID } ,
2023-02-18 19:32:59 -05:00
// resume hash is folded into ids
SuspendedPair { ids : NeededIds , attempted : Attempted , car : Rc < MarkedForm > , cdr : Rc < MarkedForm > } ,
2023-02-14 00:50:05 -05:00
2023-02-20 00:22:29 -05:00
PrimComb { name : String , takes_de : bool , wrap_level : i32 , f : fn ( BCtx , DCtx , Rc < MarkedForm > ) -> Result < ( BCtx , PossibleMarkedTailCall ) , String > } ,
2023-02-16 18:21:13 -05:00
DeriComb { ids : NeededIds , se : Rc < MarkedForm > , de : Option < String > , id : EnvID , wrap_level : i32 , sequence_params : Vec < String > , rest_params : Option < String > , body : Rc < MarkedForm > } ,
2023-02-14 00:50:05 -05:00
}
impl MarkedForm {
2023-02-18 22:46:23 -05:00
pub fn wrap_level ( & self ) -> Option < i32 > {
match self {
2023-02-20 00:22:29 -05:00
MarkedForm ::PrimComb { wrap_level , .. } = > Some ( * wrap_level ) ,
MarkedForm ::DeriComb { wrap_level , .. } = > Some ( * wrap_level ) ,
2023-02-18 22:46:23 -05:00
_ = > None ,
}
}
pub fn decrement_wrap_level ( & self ) -> Option < Rc < Self > > {
match self {
2023-02-20 00:22:29 -05:00
MarkedForm ::PrimComb { name , takes_de , wrap_level , f } = > Some ( Rc ::new ( MarkedForm ::PrimComb { name : name . clone ( ) , takes_de : * takes_de , wrap_level : wrap_level - 1 , f : * f } ) ) ,
2023-02-18 22:46:23 -05:00
MarkedForm ::DeriComb { ids , se , de , id , wrap_level , sequence_params , rest_params , body } = > Some ( Rc ::new ( MarkedForm ::DeriComb { ids : ids . clone ( ) , se : Rc ::clone ( se ) , de : de . clone ( ) , id : id . clone ( ) , wrap_level : wrap_level - 1 , sequence_params : sequence_params . clone ( ) , rest_params : rest_params . clone ( ) , body : Rc ::clone ( body ) } ) ) ,
_ = > None ,
}
}
2023-02-18 19:32:59 -05:00
pub fn ids ( & self ) -> NeededIds {
match self {
2023-02-19 01:18:59 -05:00
MarkedForm ::Nil = > NeededIds ::new_none ( ) ,
MarkedForm ::Int ( i ) = > NeededIds ::new_none ( ) ,
MarkedForm ::Bool ( b ) = > NeededIds ::new_none ( ) ,
MarkedForm ::Symbol ( s ) = > NeededIds ::new_none ( ) ,
MarkedForm ::Pair ( ids , car , cdr ) = > ids . clone ( ) ,
MarkedForm ::SuspendedSymbol ( name ) = > NeededIds ::new_true ( ) ,
MarkedForm ::SuspendedEnvLookup { id , .. } = > NeededIds ::new_single ( id . clone ( ) ) ,
MarkedForm ::SuspendedParamLookup { id , .. } = > NeededIds ::new_single ( id . clone ( ) ) ,
MarkedForm ::SuspendedPair { ids , .. } = > ids . clone ( ) ,
MarkedForm ::PrimComb { .. } = > NeededIds ::new_none ( ) ,
MarkedForm ::DeriComb { ids , .. } = > ids . clone ( ) ,
2023-02-18 19:32:59 -05:00
}
}
2023-02-20 00:22:29 -05:00
// TODO: this might be essentially the same as NeededIds.nothing_needed()
2023-02-19 00:46:54 -05:00
pub fn is_value ( & self ) -> bool {
match match self {
2023-02-19 01:18:59 -05:00
MarkedForm ::Nil = > return true ,
MarkedForm ::Int ( i ) = > return true ,
MarkedForm ::Bool ( b ) = > return true ,
MarkedForm ::Symbol ( s ) = > return true ,
MarkedForm ::SuspendedSymbol ( name ) = > return false ,
MarkedForm ::SuspendedEnvLookup { id , .. } = > return false ,
MarkedForm ::SuspendedParamLookup { id , .. } = > return false ,
MarkedForm ::SuspendedPair { ids , .. } = > return false ,
MarkedForm ::PrimComb { .. } = > return true ,
MarkedForm ::Pair ( ids , car , cdr ) = > ids . clone ( ) ,
MarkedForm ::DeriComb { ids , .. } = > ids . clone ( ) ,
2023-02-19 00:46:54 -05:00
} {
NeededIds ::True ( hashes ) = > false ,
NeededIds ::None ( hashes ) = > true ,
NeededIds ::Some ( ids , hashes ) = > false ,
}
}
2023-02-14 00:50:05 -05:00
pub fn unval ( self : & Rc < MarkedForm > ) -> Result < Rc < MarkedForm > , & 'static str > {
match & * * self {
2023-02-18 19:32:59 -05:00
MarkedForm ::Nil = > Ok ( Rc ::clone ( self ) ) ,
MarkedForm ::Int ( i ) = > Ok ( Rc ::clone ( self ) ) ,
MarkedForm ::Bool ( b ) = > Ok ( Rc ::clone ( self ) ) ,
MarkedForm ::Symbol ( s ) = > Ok ( Rc ::new ( MarkedForm ::SuspendedSymbol ( s . clone ( ) ) ) ) ,
MarkedForm ::Pair ( ids , car , cdr ) = > Ok ( Rc ::new ( MarkedForm ::SuspendedPair { ids : NeededIds ::new_true ( ) , attempted : Attempted ::False , car : car . unval ( ) ? , cdr : Rc ::clone ( cdr ) } ) ) ,
MarkedForm ::SuspendedSymbol ( name ) = > Err ( " trying to unval a suspended symbol " ) ,
2023-02-19 01:18:59 -05:00
MarkedForm ::SuspendedEnvLookup { .. } = > Err ( " trying to unval a suspended env lookup " ) ,
MarkedForm ::SuspendedParamLookup { .. } = > Err ( " trying to unval a suspended param lookup " ) ,
2023-02-18 19:32:59 -05:00
MarkedForm ::SuspendedPair { ids , .. } = > Err ( " trying to unval a suspended pair " ) ,
2023-02-16 18:21:13 -05:00
MarkedForm ::PrimComb { .. } = > Ok ( Rc ::clone ( self ) ) ,
MarkedForm ::DeriComb { .. } = > Ok ( Rc ::clone ( self ) ) ,
2023-02-14 00:50:05 -05:00
}
}
2023-02-18 19:32:59 -05:00
pub fn truthy ( & self ) -> Result < bool , & 'static str > {
match self {
MarkedForm ::Nil = > Ok ( false ) ,
MarkedForm ::Int ( i ) = > Ok ( true ) ,
MarkedForm ::Bool ( b ) = > Ok ( * b ) ,
MarkedForm ::Symbol ( s ) = > Ok ( true ) ,
MarkedForm ::Pair ( ids , car , cdr ) = > Ok ( true ) ,
MarkedForm ::SuspendedSymbol ( name ) = > Err ( " trying to truthy a suspended symbol " ) ,
2023-02-19 01:18:59 -05:00
MarkedForm ::SuspendedEnvLookup { .. } = > Err ( " trying to truthy a suspended env lookup " ) ,
MarkedForm ::SuspendedParamLookup { .. } = > Err ( " trying to truthy a suspended param lookup " ) ,
2023-02-18 19:32:59 -05:00
MarkedForm ::SuspendedPair { ids , .. } = > Err ( " trying to truthy a suspended pair " ) ,
MarkedForm ::PrimComb { .. } = > Ok ( true ) ,
MarkedForm ::DeriComb { .. } = > Ok ( true ) ,
}
}
pub fn sym ( & self ) -> Result < & str , & 'static str > {
match self {
MarkedForm ::Symbol ( s ) = > Ok ( s ) ,
_ = > Err ( " not a symbol " ) ,
}
}
pub fn int ( & self ) -> Result < i32 , & 'static str > {
match self {
MarkedForm ::Int ( i ) = > Ok ( * i ) ,
_ = > Err ( " not a int " ) ,
}
}
pub fn car ( & self ) -> Result < Rc < MarkedForm > , & 'static str > {
match self {
MarkedForm ::Pair ( ids , car , cdr ) = > Ok ( Rc ::clone ( car ) ) ,
_ = > Err ( " not a pair " ) ,
}
}
pub fn cdr ( & self ) -> Result < Rc < MarkedForm > , & 'static str > {
match self {
MarkedForm ::Pair ( ids , car , cdr ) = > Ok ( Rc ::clone ( cdr ) ) ,
_ = > Err ( " not a pair " ) ,
}
}
2023-02-14 00:50:05 -05:00
}
impl fmt ::Display for MarkedForm {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
match self {
2023-02-18 19:32:59 -05:00
MarkedForm ::Nil = > write! ( f , " nil " ) ,
MarkedForm ::Int ( i ) = > write! ( f , " {} " , i ) ,
MarkedForm ::Bool ( b ) = > write! ( f , " {} " , b ) ,
MarkedForm ::Symbol ( s ) = > write! ( f , " {} " , s ) ,
MarkedForm ::Pair ( ids , car , cdr ) = > {
2023-02-18 22:46:23 -05:00
//write!(f, "{:?}#({}", ids, car)?;
write! ( f , " ({} " , car ) ? ;
2023-02-18 19:32:59 -05:00
let mut traverse : Rc < MarkedForm > = Rc ::clone ( cdr ) ;
loop {
match & * traverse {
MarkedForm ::Pair ( ref ids , ref carp , ref cdrp ) = > {
write! ( f , " {} " , carp ) ? ;
traverse = Rc ::clone ( cdrp ) ;
} ,
MarkedForm ::Nil = > {
write! ( f , " ) " ) ? ;
return Ok ( ( ) ) ;
} ,
x = > {
write! ( f , " . {}) " , x ) ? ;
return Ok ( ( ) ) ;
} ,
}
}
} ,
2023-02-19 01:18:59 -05:00
MarkedForm ::SuspendedSymbol ( name ) = > write! ( f , " {} " , name ) ,
MarkedForm ::SuspendedEnvLookup { name , id } = > write! ( f , " {:?}({:?}env) " , name , id ) ,
MarkedForm ::SuspendedParamLookup { name , id , cdr_num , car } = > write! ( f , " {:?}({:?}{}{}) " , name , id , cdr_num , car ) ,
MarkedForm ::PrimComb { name , wrap_level , .. } = > write! ( f , " <{}{}> " , name , wrap_level ) ,
2023-02-14 00:50:05 -05:00
2023-02-19 20:33:09 -05:00
//MarkedForm::DeriComb { ids, se, de, id, wrap_level, sequence_params, rest_params, body } => write!(f, "{:?}#[{}/{:?}/{:?}/{}/{:?}/{:?}/{}]", ids, se, de, id, wrap_level, sequence_params, rest_params, body),
MarkedForm ::DeriComb { ids , se , de , id , wrap_level , sequence_params , rest_params , body } = > write! ( f , " {:?}#[/{:?}/{:?}/{}/{:?}/{:?}/{}] " , ids , de , id , wrap_level , sequence_params , rest_params , body ) ,
2023-02-14 00:50:05 -05:00
2023-02-18 19:32:59 -05:00
MarkedForm ::SuspendedPair { ids , attempted , car , cdr } = > {
2023-02-18 22:46:23 -05:00
//write!(f, "{:?}{:?}#{{{}", ids, attempted, car)?;
write! ( f , " {{{} " , car ) ? ;
2023-02-14 00:50:05 -05:00
let mut traverse : Rc < MarkedForm > = Rc ::clone ( cdr ) ;
loop {
match & * traverse {
2023-02-18 19:32:59 -05:00
MarkedForm ::Pair ( ref ids , ref carp , ref cdrp ) = > {
2023-02-14 00:50:05 -05:00
write! ( f , " {} " , carp ) ? ;
traverse = Rc ::clone ( cdrp ) ;
} ,
2023-02-18 22:46:23 -05:00
MarkedForm ::Nil = > {
write! ( f , " }} " ) ? ;
return Ok ( ( ) ) ;
} ,
2023-02-14 00:50:05 -05:00
x = > {
write! ( f , " . {}}} " , x ) ? ;
return Ok ( ( ) ) ;
} ,
}
}
} ,
}
}
}
2023-02-16 18:21:13 -05:00
pub fn eval ( e : Rc < Form > , f : Rc < Form > ) -> Rc < Form > {
let mut e = e ;
let mut x = Option ::Some ( f ) ;
loop {
let cur = x . take ( ) . unwrap ( ) ;
//println!("Evaluating {:?} in {:?}", cur, e);
match * cur {
Form ::Symbol ( ref s ) = > {
let mut t = e ;
//println!("Looking up {} in {:?}", s, t);
//println!("Looking up {}", s);
while s ! = t . car ( ) . unwrap ( ) . car ( ) . unwrap ( ) . sym ( ) . unwrap ( ) {
t = t . cdr ( ) . unwrap ( ) ;
}
return t . car ( ) . unwrap ( ) . cdr ( ) . unwrap ( ) ;
} ,
Form ::Pair ( ref c , ref p ) = > {
let comb = eval ( Rc ::clone ( & e ) , Rc ::clone ( c ) ) ;
match * comb {
Form ::PrimComb ( ref _n , ref f ) = > match f ( e , Rc ::clone ( p ) ) {
PossibleTailCall ::Result ( r ) = > return r ,
PossibleTailCall ::TailCall ( ne , nx ) = > {
e = ne ;
x = Some ( nx ) ;
} ,
} ,
Form ::DeriComb { ref se , ref de , ref params , ref body } = > {
let mut new_e = Rc ::clone ( se ) ;
if let Some ( de ) = de {
new_e = assoc ( de , Rc ::clone ( & e ) , new_e ) ;
}
new_e = assoc ( params , Rc ::clone ( p ) , new_e ) ;
// always a tail call
e = new_e ;
x = Some ( Rc ::clone ( body ) ) ;
} ,
_ = > panic! ( " Tried to call not a Prim/DeriComb {:?} " , comb ) ,
}
} ,
_ = > return cur ,
}
}
}
2023-02-19 00:46:54 -05:00
fn massoc ( k : & str , v : Rc < MarkedForm > , l : Rc < MarkedForm > ) -> Rc < MarkedForm > {
Rc ::new ( MarkedForm ::Pair (
l . ids ( ) . union ( & v . ids ( ) ) ,
Rc ::new ( MarkedForm ::Pair (
v . ids ( ) ,
Rc ::new ( MarkedForm ::Symbol ( k . to_owned ( ) ) ) ,
v ) ) ,
l ) )
}
2023-02-16 18:21:13 -05:00
fn assoc ( k : & str , v : Rc < Form > , l : Rc < Form > ) -> Rc < Form > {
Rc ::new ( Form ::Pair (
Rc ::new ( Form ::Pair (
Rc ::new ( Form ::Symbol ( k . to_owned ( ) ) ) ,
v ) ) ,
l ) )
}
fn assoc_vec ( kvs : Vec < ( & str , Rc < Form > ) > ) -> Rc < Form > {
let mut to_ret = Rc ::new ( Form ::Nil ) ;
for ( k , v ) in kvs {
to_ret = assoc ( k , v , to_ret ) ;
}
to_ret
}
pub fn root_env ( ) -> Rc < Form > {
assoc_vec ( vec! [
// TODO: Should be properly tail recursive
( " eval " , Rc ::new ( Form ::PrimComb ( " eval " . to_owned ( ) , | e , p | {
let b = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) ;
2023-02-18 19:32:59 -05:00
let e = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) ;
2023-02-16 18:21:13 -05:00
PossibleTailCall ::TailCall ( e , b )
} ) ) ) ,
// (vau de params body)
( " vau " , Rc ::new ( Form ::PrimComb ( " vau " . to_owned ( ) , | e , p | {
let de = p . car ( ) . unwrap ( ) . sym ( ) . map ( | s | s . to_owned ( ) ) ;
let params = p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) . sym ( ) . unwrap ( ) . to_owned ( ) ;
let body = p . cdr ( ) . unwrap ( ) . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::DeriComb { se : e , de , params , body } ) )
} ) ) ) ,
( " = " , Rc ::new ( Form ::PrimComb ( " = " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Bool ( a = = b ) ) )
} ) ) ) ,
( " < " , Rc ::new ( Form ::PrimComb ( " < " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Bool ( a . int ( ) . unwrap ( ) < b . int ( ) . unwrap ( ) ) ) )
} ) ) ) ,
( " > " , Rc ::new ( Form ::PrimComb ( " > " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Bool ( a . int ( ) . unwrap ( ) > b . int ( ) . unwrap ( ) ) ) )
} ) ) ) ,
( " <= " , Rc ::new ( Form ::PrimComb ( " <= " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Bool ( a . int ( ) . unwrap ( ) < = b . int ( ) . unwrap ( ) ) ) )
} ) ) ) ,
( " >= " , Rc ::new ( Form ::PrimComb ( " >= " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Bool ( a . int ( ) . unwrap ( ) > = b . int ( ) . unwrap ( ) ) ) )
} ) ) ) ,
( " if " , Rc ::new ( Form ::PrimComb ( " if " . to_owned ( ) , | e , p | {
if eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) . truthy ( ) {
PossibleTailCall ::TailCall ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) )
} else {
2023-02-18 19:32:59 -05:00
PossibleTailCall ::TailCall ( e , p . cdr ( ) . unwrap ( ) . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) )
2023-02-16 18:21:13 -05:00
}
} ) ) ) ,
( " cons " , Rc ::new ( Form ::PrimComb ( " cons " . to_owned ( ) , | e , p | {
let h = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) ;
let t = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Pair ( h , t ) ) )
} ) ) ) ,
( " car " , Rc ::new ( Form ::PrimComb ( " car " . to_owned ( ) , | e , p | {
PossibleTailCall ::Result ( eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) . car ( ) . unwrap ( ) )
} ) ) ) ,
( " cdr " , Rc ::new ( Form ::PrimComb ( " cdr " . to_owned ( ) , | e , p | {
PossibleTailCall ::Result ( eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) . cdr ( ) . unwrap ( ) )
} ) ) ) ,
( " quote " , Rc ::new ( Form ::PrimComb ( " quote " . to_owned ( ) , | _e , p | {
PossibleTailCall ::Result ( p . car ( ) . unwrap ( ) )
} ) ) ) ,
( " debug " , Rc ::new ( Form ::PrimComb ( " debug " . to_owned ( ) , | e , p | {
//println!("Debug: {:?}", eval(Rc::clone(&e), p.car().unwrap()));
println! ( " Debug: {} " , eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) ) ;
PossibleTailCall ::TailCall ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) )
} ) ) ) ,
( " assert " , Rc ::new ( Form ::PrimComb ( " assert " . to_owned ( ) , | e , p | {
let thing = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) ;
if ! thing . truthy ( ) {
println! ( " Assert failed: {:?} " , thing ) ;
}
assert! ( thing . truthy ( ) ) ;
PossibleTailCall ::TailCall ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) )
} ) ) ) ,
( " + " , Rc ::new ( Form ::PrimComb ( " + " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Int ( a + b ) ) )
} ) ) ) ,
( " - " , Rc ::new ( Form ::PrimComb ( " - " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Int ( a - b ) ) )
} ) ) ) ,
( " * " , Rc ::new ( Form ::PrimComb ( " * " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Int ( a * b ) ) )
} ) ) ) ,
( " / " , Rc ::new ( Form ::PrimComb ( " / " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Int ( a / b ) ) )
} ) ) ) ,
( " % " , Rc ::new ( Form ::PrimComb ( " % " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Int ( a % b ) ) )
} ) ) ) ,
( " & " , Rc ::new ( Form ::PrimComb ( " & " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Int ( a & b ) ) )
} ) ) ) ,
( " | " , Rc ::new ( Form ::PrimComb ( " | " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Int ( a | b ) ) )
} ) ) ) ,
( " ^ " , Rc ::new ( Form ::PrimComb ( " ^ " . to_owned ( ) , | e , p | {
let a = eval ( Rc ::clone ( & e ) , p . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
let b = eval ( e , p . cdr ( ) . unwrap ( ) . car ( ) . unwrap ( ) ) . int ( ) . unwrap ( ) ;
PossibleTailCall ::Result ( Rc ::new ( Form ::Int ( a ^ b ) ) )
} ) ) ) ,
( " comb? " , Rc ::new ( Form ::PrimComb ( " comb? " . to_owned ( ) , | e , p | {
PossibleTailCall ::Result ( Rc ::new ( Form ::Bool ( match & * eval ( e , p . car ( ) . unwrap ( ) ) {
Form ::PrimComb ( _n , _f ) = > true ,
Form ::DeriComb { .. } = > true ,
_ = > false ,
} ) ) )
} ) ) ) ,
( " pair? " , Rc ::new ( Form ::PrimComb ( " pair? " . to_owned ( ) , | e , p | {
PossibleTailCall ::Result ( Rc ::new ( Form ::Bool ( match & * eval ( e , p . car ( ) . unwrap ( ) ) {
Form ::Pair ( _a , _b ) = > true ,
_ = > false ,
} ) ) )
} ) ) ) ,
( " symbol? " , Rc ::new ( Form ::PrimComb ( " symbol? " . to_owned ( ) , | e , p | {
PossibleTailCall ::Result ( Rc ::new ( Form ::Bool ( match & * eval ( e , p . car ( ) . unwrap ( ) ) {
Form ::Symbol ( _ ) = > true ,
_ = > false ,
} ) ) )
} ) ) ) ,
( " int? " , Rc ::new ( Form ::PrimComb ( " int? " . to_owned ( ) , | e , p | {
PossibleTailCall ::Result ( Rc ::new ( Form ::Bool ( match & * eval ( e , p . car ( ) . unwrap ( ) ) {
Form ::Int ( _ ) = > true ,
_ = > false ,
} ) ) )
} ) ) ) ,
// maybe bool? but also could be derived. Nil def
( " bool? " , Rc ::new ( Form ::PrimComb ( " bool? " . to_owned ( ) , | e , p | {
PossibleTailCall ::Result ( Rc ::new ( Form ::Bool ( match & * eval ( e , p . car ( ) . unwrap ( ) ) {
Form ::Bool ( _ ) = > true ,
_ = > false ,
} ) ) )
} ) ) ) ,
( " nil? " , Rc ::new ( Form ::PrimComb ( " nil? " . to_owned ( ) , | e , p | {
PossibleTailCall ::Result ( Rc ::new ( Form ::Bool ( match & * eval ( e , p . car ( ) . unwrap ( ) ) {
Form ::Nil = > true ,
_ = > false ,
} ) ) )
} ) ) ) ,
// consts
( " true " , Rc ::new ( Form ::Bool ( true ) ) ) ,
( " false " , Rc ::new ( Form ::Bool ( false ) ) ) ,
( " nil " , Rc ::new ( Form ::Nil ) ) ,
] )
}