Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🧼 other miscellaneous tidying #12

Merged
merged 4 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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