Skip to content

Commit

Permalink
Merge pull request #12 from cratelyn/clean
Browse files Browse the repository at this point in the history
🧼 other miscellaneous tidying
  • Loading branch information
cratelyn authored Nov 23, 2023
2 parents 64b81ed + 75ca47a commit 8c53847
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 51 deletions.
41 changes: 12 additions & 29 deletions src/a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,26 @@ use super::*; use std::marker::PhantomData as PD;
toob!(i00_for_3x3,arr3x3,0,0);toob!(i01_for_3x3,arr3x3,0,1);toob!(i14_for_3x3,arr3x3,1,4);
toob!(i41_for_3x3,arr3x3,4,1);toob!(i44_for_3x3,arr3x3,4,4);
ti!(i11_for_3x3,arr3x3,1,1,0);ti!(i21_for_3x3,arr3x3,2,1,3);ti!(i22_for_3x3,arr3x3,2,2,4);
ti!(i31_for_3x3,arr3x3,3,1,6);ti!(i33_for_3x3,arr3x3,3,3,8);
}
ti!(i31_for_3x3,arr3x3,3,1,6);ti!(i33_for_3x3,arr3x3,3,3,8); }

/**array allocation*/mod alloc{use{super::*,std::alloc::{alloc,alloc_zeroed,dealloc}};
/**sealed trait, memory markers*/pub trait MX{} impl MX for MU {} impl MX for MI {}
/**marker: memory uninitialized*/#[derive(CL,DBG)]pub struct MU;
/**marker: memory initialized*/ #[derive(CL,DBG)]pub struct MI;
impl A<MU>{
pub fn new(m:U,n:U)->R<Self>{Self::alloc(m,n).map(|(l,d)|A{m,n,d,l,i:PD})}
// TODO: use `A::iter`
// TODO: use `set_unchecked` here.
pub fn init_with<F:FnMut(U,U)->R<I>>(mut self,mut f:F)->R<A<MI>>{let(A{m,n,..})=self;
for(i)in(1..=m){for(j)in(1..=n){let(v)=f(i,j)?;self.set(i,j,v)?;}}Ok(unsafe{self.finish()})}
pub unsafe fn finish(self)->A<MI>{std::mem::transmute(self)}
}
pub unsafe fn finish(self)->A<MI>{std::mem::transmute(self)}}
impl A<MI>{
pub fn zeroed(m:U,n:U)->R<Self>{let(l,d)=Self::allocz(m,n)?;Ok(A{m,n,d,l,i:PD})}
pub fn from_i(i:I)->R<Self>{let mut a=A::new(1,1)?;a.set(1,1,i)?;Ok(unsafe{a.finish()})}}
impl TF<I> for A<MI>{type Error=E;fn try_from(i:I)->R<Self>{A::from_i(i)}}
impl<X:MX> A<X>{
fn alloc(m:U,n:U)->R<(L,*mut u8)>{let(l)=Self::l(m,n)?;let d=unsafe{alloc(l)};Ok((l,d))}
fn alloc (m:U,n:U)->R<(L,*mut u8)>{let(l)=Self::l(m,n)?;let d=unsafe{alloc(l)}; Ok((l,d))}
fn allocz(m:U,n:U)->R<(L,*mut u8)>{let(l)=Self::l(m,n)?;let d=unsafe{alloc_zeroed(l)};Ok((l,d))}
fn l(m:U,n:U)->R<L>{L::array::<I>(m*n).map_err(E::from)}
}
fn l(m:U,n:U)->R<L>{L::array::<I>(m*n).map_err(E::from)}}
impl<M> Drop for A<M>{fn drop(&mut self){let(A{d,l,..})=self;unsafe{dealloc(*d,*l)}}}
// TODO: add compile_fail checks to ensure that e.g. `get` cannot be used on an uninitialized array
} pub use self::alloc::{MI,MU,MX};

/**array access*/mod access{use{super::*,std::mem::size_of};
Expand All @@ -86,8 +80,7 @@ use super::*; use std::marker::PhantomData as PD;
pub(crate)fn ptr_at_uc(&self,i:U,j:U)->R<*mut I>{self.ptr_at_impl(i,j,Self::index_uc)}
fn ptr_at_impl<F:Fn(&Self,U,U)->R<U>>(&self,i:U,j:U,f:F)->R<*mut I>{
let(o):isize=f(self,i,j).map(|x|x*size_of::<I>())?.try_into()?;let(d)=unsafe{(self.d.offset(o) as *mut I)};
Ok(d)}
}}
Ok(d)}}}

/**scalar conversion/comparison*/mod scalars{use super::*; /*todo...*/
impl A<MI>{pub fn as_i(&self)->R<I>{let a@A{m:1,n:1,..}=self else{bail!("not a scalar")};a.get(1,1)}}
Expand Down Expand Up @@ -123,8 +116,7 @@ use super::*; use std::marker::PhantomData as PD;
if(r.len()!=self.m){r!(false)}for(i,r_i)in(r.into_iter().enumerate()){
if(r_i.len()!=self.n){r!(false)}for(j,r_ij)in(r_i.into_iter().enumerate()){
let(i,j)=(i+1,j+1);let(a_ij)=match(self.get(i,j)){Ok(v)=>v,Err(_)=>r!(false)};
if(a_ij)!=(*r_ij){r!(false)}}}true}}
}
if(a_ij)!=(*r_ij){r!(false)}}}true}}}

/**monadic verbs*/impl A{
pub fn m_same(self)->R<A>{Ok(self)}
Expand All @@ -138,8 +130,7 @@ use super::*; use std::marker::PhantomData as PD;
pub fn m_tally(self)->R<A>{let A{m,n,..}=self;let(i)=I::try_from(m*n)?;A::from_i(i)}
pub fn m_trans(self)->R<A>{let(i@A{m:m_i,n:n_i,..})=self;let(m_o,n_o)=(n_i,m_i);
let(f)=|i_o,j_o|{i.get(j_o,i_o)};A::new(m_o,n_o)?.init_with(f)}
pub fn m_inc(self)->R<A>{let(a@A{m,n,..})=self;A::new(m,n)?.init_with(|i,j|a.get(i,j).map(|x|x+1))}
}
pub fn m_inc(self)->R<A>{let(a@A{m,n,..})=self;A::new(m,n)?.init_with(|i,j|a.get(i,j).map(|x|x+1))}}

/**dyadic verbs*/impl D{
/*return dyad function**/ pub fn f(&self)->fn(I,I)->I{use D::*;
Expand All @@ -163,8 +154,7 @@ use super::*; use std::marker::PhantomData as PD;
else if (ml==nr)&&(nl==mr) /*NB: inherit the dimensions of the right-hand operand.*/ // rotation
{let(f)=|i,j|{let(x)=l.get(j,i)?;let(y)=r.get(i,j)?;Ok(f(x,y))};r!(A::new(mr,nr)?.init_with(f))}
bail!("length error");
}
}
}}

/**monadic adverbs*/mod adverbs_m{use super::*;
impl Ym{
Expand All @@ -177,17 +167,15 @@ use super::*; use std::marker::PhantomData as PD;
else if let Ok(s)=a.as_slice(){let (m,n)=(s.len(),s.len());
let p=|i,j|if(j>i){Ok(0)}else{a.get(1,j).map(d_)};
A::new(m,n)?.init_with(p)}
else { bail!("monadic `\\` is not implemented for matrices") }}
}
else { bail!("monadic `\\` is not implemented for matrices") }}}
// === monadic `/`, `Ym::Insert` tests
macro_rules! test_insert{($f:ident,$d:expr,$a:expr,$o:expr)=>
{#[test]fn $f()->R<()>{let(a):R<A>={$a};let(d):D={$d}; // typecheck macro arguments.
let i:I=a.and_then(|a:A|Ym::insert($d,a)).and_then(|a|a.as_i())?;
eq!(i,$o);ok!()}}}
test_insert!(add_a_scalar, D::Plus, A::from_i(42), 42 );
test_insert!(add_a_sequence, D::Plus, <A as TF<&[I]>>::try_from(&[1,2,3,4,5]), (1+2+3+4+5) );
test_insert!(mul_a_sequence, D::Mul , <A as TF<&[I]>>::try_from(&[1,2,3,4,5]), (1*2*3*4*5) );
}
test_insert!(mul_a_sequence, D::Mul , <A as TF<&[I]>>::try_from(&[1,2,3,4,5]), (1*2*3*4*5) ); }

/**dyadic adverbs*/mod adverbs_d{use super::*;
impl Yd{
Expand All @@ -203,17 +191,12 @@ use super::*; use std::marker::PhantomData as PD;
fn infix(d:D,l:A,r:A)->R<A>{let(s)=r.as_slice().map_err(|_|err!("infix rhs must be a slice"))?;
let(il)=l.as_i() .map_err(|_|err!("infix lhs must be a scalar"))?.try_into()?;
let(ic)=(s.len()-il)+1;
A::new(ic,il)?.init_with(|i,j|Ok(s[(i-1)+(j-1)]))}
}
}
A::new(ic,il)?.init_with(|i,j|Ok(s[(i-1)+(j-1)]))}}}

/**deep-copy*/impl A<MI>{
pub fn deep_copy(&self)->R<A>{let A{m,n,l:li,d:di,i:_}=*self;A::new(m,n)?.init_with(|i,j|{self.get(i,j)})}
}
pub fn deep_copy(&self)->R<A>{let A{m,n,l:li,d:di,i:_}=*self;A::new(m,n)?.init_with(|i,j|{self.get(i,j)})}}

/**display*/mod fmt{use super::*;
impl DS for A<MI>{
// TODO: buffer stdout, flush after loops
// TODO: use `unchecked` to elide bounds checks in printing
fn fmt(&self,fmt:&mut FMT)->FR{let A{m,n,..}=*self;for(i,j)in(self.iter())
{let(x)=self.get_uc(i,j).map_err(|_|std::fmt::Error)?;write!(fmt,"{x}{}",if(j==n){'\n'}else{' '})?;}ok!()}}}
23 changes: 11 additions & 12 deletions src/j.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ pub use self::{a::*,r::*,s::*};
pub fn eval(input:&str,st:&mut ST)->R<O<A>>{
let(mut ts)=lex(input)?;let(ast)=match(parse(&mut ts)?){Some(x)=>x,None=>rrn!()};eval_(ast,st)}
fn eval_(ast:B<N>,st:&mut ST)->R<O<A>>{use{M::*,D::*};
let(mut rec)=|a|->R<A>{match(eval_(a,st)){Ok(Some(a))=>Ok(a),Err(e)=>Err(e), // recursively evaluate subexpression.
let(mut rec)=|a|->R<A>{match(eval_(a,st)){Ok(Some(a))=>Ok(a),Err(e)=>Err(e),/*recursively evaluate*/
Ok(None)=>Err(err!("expression did not result in a value"))}};
match *ast{
N::A{a} =>Ok(a),
N::M{m,o} =>{let(a)=rec(o)?; match m{Idot=>a.m_idot(), Shape=>a.m_shape(), Same=>a.m_same(),
Tally=>a.m_tally(),Transpose=>a.m_trans(), Inc=>a.m_inc()}}
N::D{d,l,r}=>{let(l,r)=(rec(l)?,rec(r)?);match d{Plus=>l.d_plus(r), Mul=>l.d_mul(r),
Left=>l.d_left(r), Right=>l.d_right(r)}}
N::Ym{ym,d,o}=>{rec(o).and_then(|a|ym.apply(d,a))}
N::Yd{yd,d,l,r}=>{let(l,r)=(rec(l)?,rec(r)?);yd.apply(d,l,r)}
N::S{sy} =>{st.get(&sy).ok_or(err!("undefined symbol: {sy:?}")).and_then(A::deep_copy)}
N::E{sy,e} =>{let(a)=rec(e)?;st.insert(sy,a);r!(Ok(None))}
}.map(O::Some)}
match *ast{N::A{a}=>Ok(a), // array literal
N::M{m,o }=>{let(a)=rec(o)?; match m{Idot=>a.m_idot(),Shape=>a.m_shape(),Transpose=>a.m_trans(), // monadic verb
Same=>a.m_same(),Tally=>a.m_tally(),Inc=>a.m_inc()}}
N::D{d,l,r }=>{let(l,r)=(rec(l)?,rec(r)?);match d{Plus=>l.d_plus(r),Mul=>l.d_mul(r), // dyadic verb
Left=>l.d_left(r),Right=>l.d_right(r)}}
N::Ym{ym,d,o }=>{rec(o).and_then(|a|ym.apply(d,a))} // monadic adverb
N::Yd{yd,d,l,r}=>{let(l,r)=(rec(l)?,rec(r)?);yd.apply(d,l,r)} // dyadic adverb
N::E {sy,e }=>{let(a)=rec(e)?;st.insert(sy,a);r!(Ok(None))} // symbol assignment
N::S {sy }=>{st.get(&sy).ok_or(err!("undefined symbol: {sy:?}")).and_then(A::deep_copy)} // symbol
}.map(O::Some)}
5 changes: 1 addition & 4 deletions src/p.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,4 @@ pub(crate)use{anyhow::{Context,Error as E,anyhow as err,bail}};
#[macro_export] /**`unreachable!()`*/ macro_rules! ur {()=>{unreachable!()}}
/**`Result<T, anyhow::Error>`*/ pub type R<T> = Result<T,E>;
#[cfg(test)]/**test prelude*/pub(crate) mod tp{
pub(crate) use{assert_eq as eq,assert_ne as neq,assert as is,vec as v};
}
// todo: extension trait for abbreviated `try_into`, `try_from`
// todo: extension trait for abbreviated `map`, `and_then`, `unwrap`
pub(crate) use{assert_eq as eq,assert_ne as neq,assert as is,vec as v}; }
12 changes: 6 additions & 6 deletions src/s.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ use super::*; use std::ops::Not;
let(sv)=|c:&char|c.is_ascii_lowercase()||c.is_ascii_digit()||*c=='_'; // validate
if(sc.iter().all(sv).not()){bail!("symbols may only contain a-z, 0-9, or `_`")}
Ok(SY(s.to_owned()))}}
#[test] fn simple_symbol_succeeds() {assert!(SY::from_str("abc") .is_ok())}
#[test] fn underscore_symbol_succeeds() {assert!(SY::from_str("abc_def").is_ok())}
#[test] fn trailing_number_symbol_succeeds(){assert!(SY::from_str("a1") .is_ok())}
#[test] fn empty_symbol_fails() {assert!(SY::from_str("") .is_err())}
#[test] fn number_symbol_fails() {assert!(SY::from_str("1") .is_err())}
#[test] fn leading_number_symbol_fails() {assert!(SY::from_str("1a") .is_err())}
#[test] fn simple_symbol_succeeds() {is!(SY::from_str("abc") .is_ok())}
#[test] fn underscore_symbol_succeeds() {is!(SY::from_str("abc_def").is_ok())}
#[test] fn trailing_number_symbol_succeeds(){is!(SY::from_str("a1") .is_ok())}
#[test] fn empty_symbol_fails() {is!(SY::from_str("") .is_err())}
#[test] fn number_symbol_fails() {is!(SY::from_str("1") .is_err())}
#[test] fn leading_number_symbol_fails() {is!(SY::from_str("1a") .is_err())}
}

impl ST{
Expand Down

0 comments on commit 8c53847

Please sign in to comment.