From 3b83e91d1a688759ff7b495b20be0e9ea2504052 Mon Sep 17 00:00:00 2001 From: katelyn martin Date: Thu, 23 Nov 2023 17:33:24 -0500 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=A7=9F=20fix=20`dead=5Fcode`=20lints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/a.rs | 6 +++--- src/j.rs | 2 +- src/r.rs | 14 +------------- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/a.rs b/src/a.rs index 8072d32..4f239ba 100644 --- a/src/a.rs +++ b/src/a.rs @@ -27,17 +27,17 @@ use super::*; use std::marker::PhantomData as PD; #[macro_export] macro_rules! toob{($f:ident,$a:ident,$i:literal,$j:literal)=> {#[test] fn $f()->R<()>{is!($a()?.index($i,$j).is_err());ok!()}}} // === 1x1 array indexing === - fn sca()->R{let Ok(a@A{m:1,n:1,..})=A::from_i(42)else{bail!("bad dims")};Ok(a)} + #[cfg(test)] fn sca()->R{let Ok(a@A{m:1,n:1,..})=A::from_i(42)else{bail!("bad dims")};Ok(a)} toob!(i00_for_scalar,sca,0,0);toob!(i10_for_scalar,sca,1,0);toob!(i01_for_scalar,sca,0,1); toob!(i21_for_scalar,sca,2,1);toob!(i12_for_scalar,sca,1,2);toob!(i22_for_scalar,sca,2,2); ti!(i11_for_scalar,sca,1,1,0); // === 2x3 array indexing === - fn arr2x3()->R{let Ok(a@A{m:2,n:3,..})=A::zeroed(2,3)else{bail!("bad dims")};Ok(a)} + #[cfg(test)] fn arr2x3()->R{let Ok(a@A{m:2,n:3,..})=A::zeroed(2,3)else{bail!("bad dims")};Ok(a)} toob!(i00_for_2x3,arr2x3,0,0);toob!(i01_for_2x3,arr2x3,0,1);toob!(i10_for_2x3,arr2x3,1,0); ti!(i11_for_2x3,arr2x3,1,1,0);ti!(i12_for_2x3,arr2x3,1,2,1);ti!(i13_for_2x3,arr2x3,1,3,2); ti!(i21_for_2x3,arr2x3,2,1,3);ti!(i22_for_2x3,arr2x3,2,2,4);ti!(i23_for_2x3,arr2x3,2,3,5); // === 3x3 array indexing === - fn arr3x3()->R{let Ok(a@A{m:3,n:3,..})=A::zeroed(3,3)else{bail!("bad dims")};Ok(a)} + #[cfg(test)] fn arr3x3()->R{let Ok(a@A{m:3,n:3,..})=A::zeroed(3,3)else{bail!("bad dims")};Ok(a)} 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); diff --git a/src/j.rs b/src/j.rs index 057189f..d0367e7 100644 --- a/src/j.rs +++ b/src/j.rs @@ -1,4 +1,4 @@ -#![allow(dead_code,unused_variables,unreachable_code,unused_imports,unused_parens)] +#![allow(unused_variables,unreachable_code,unused_imports,unused_parens)] /**prelude*/mod p;use p::*;#[cfg(test)]use p::tp::*; /**array*/mod a; /**read input*/mod r; /**symbol table*/mod s; pub use self::{a::*,r::*,s::*}; diff --git a/src/r.rs b/src/r.rs index 45820b2..de1e061 100644 --- a/src/r.rs +++ b/src/r.rs @@ -4,7 +4,6 @@ mod lex{use crate::*; /*assignment*/ E , /* NB: this does not identify whether possible verbs */ /*(ad)verb*/ V(S) , /* are monadic or dyadic. that is done during parsing.*/ /*symbol*/ SY(SY) } - impl T{pub(super) fn is_noun(&self)->bool{use T::*;matches!(self,A(_)|SY(_))}} pub(crate) fn lex(input:&str)->R>{use std::ops::Deref; let(mut ts)=input.split_whitespace().peekable(); let(mut o)=V::with_capacity(ts.size_hint().0); while let Some(t) =ts.next(){ @@ -89,18 +88,7 @@ mod lex{use crate::*; None =>{ ym!();} Some(T::A(v)) =>{let(l)=b!(v.try_into()?);yd!(l);} Some(t@T::E|t@T::V(_))=>{ts.push(t);ym!();} Some(T::SY(sy))=>{let(l)=b!(sy.into()); yd!(l);} } - bail!("fallthrough: unexpected parsing error"); - } - /**get a tuple, representing a window peeking on the next two elements in this token stream.*/ - fn lhs_window(ts:&[T])->(O<&T>,O<&T>){match ts{ - []=>(None,None), [a]=>(None,Some(&a)), [a,b]=>(Some(&a),Some(&b)), [..,a,b]=>(Some(&a),Some(&b)) } } - #[cfg(test)]mod lhs_t{use super::*; - #[test] fn lhs_window_works_on_empty(){is!(matches!(lhs_window(&[]), (None, None))) } - #[test] fn lhs_window_works_on_one (){is!(matches!(lhs_window(&[T::E]), (None, Some(_)))) } - #[test] fn lhs_window_works_on_two (){is!(matches!(lhs_window(&[T::E,T::A(v![])]),(Some(T::E),Some(T::A(_)))))} - #[test] fn lhs_window_works_on_three(){ - is!(matches!(lhs_window(&[T::E,T::A(v![]),T::V(S::from("+"))]),(Some(T::A(_)),Some(_))))} - } + bail!("fallthrough: unexpected parsing error");} impl M {fn new(s:&str)->O {use M::*; Some(match s{"i."=>Idot ,"$" =>Shape ,"|:"=>Transpose , "#" =>Tally ,"[" =>Same ,"]" =>Same , From 28e44f745c6873bcf3435bb6d4f93fe6d543a851 Mon Sep 17 00:00:00 2001 From: katelyn martin Date: Thu, 23 Nov 2023 17:42:01 -0500 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=8D=8D=20fix=20`unused=5Fvariables`?= =?UTF-8?q?=20lints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/a.rs | 22 ++++++++++------------ src/j.rs | 2 +- src/r.rs | 6 ++++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/a.rs b/src/a.rs index 4f239ba..be80d81 100644 --- a/src/a.rs +++ b/src/a.rs @@ -15,9 +15,9 @@ use super::*; use std::marker::PhantomData as PD; fn oob(&self,i:U,j:U)->R<()>{let A{m,n,..}=*self; if(i==0||j==0||i>m||j>n){bail!("({i},{j}) is out-of-bounds of ({m},{n})")}ok!()} /// returns the scalar `A_ij` within this array. returns an error if position is out-of-bounds. - pub fn index(&self,i:U,j:U)->R {self.oob(i,j)?;let A{m,n,..}=*self;let(i,j)=(i-1,j-1);Ok((i*n)+j)} + pub fn index(&self,i:U,j:U)->R {self.oob(i,j)?;let(i,j)=(i-1,j-1);Ok((i*self.n)+j)} /// returns the scalar `A_ij` within this array. does not check if the position is in bounds. - pub fn index_uc(&self,i:U,j:U)->R{ let A{m,n,..}=*self;let(i,j)=(i-1,j-1);Ok((i*n)+j)} + pub fn index_uc(&self,i:U,j:U)->R{ let(i,j)=(i-1,j-1);Ok((i*self.n)+j)} } // === test helpers === /// `A::index` test case generator. check that indexing at a position returns the expected value. @@ -111,8 +111,7 @@ use super::*; use std::marker::PhantomData as PD; impl A{ // only allow matrix access for initialized arrays pub fn into_matrix(&self)->R>{let(A{m,n,..})=*self; (0..m).map(|m|{self.ptr_at(m+1,1)}).map(|r|r.map(|d|unsafe{from_raw_parts(d as *mut I, n as U)})).collect()}} - impl TF<&[&[I]]> for A{type Error=E;fn try_from(s:&[&[I]])->R{todo!("TF<&[I]> for A")}} - impl PE<&[&[I]]> for A{fn eq(&self,r:&&[&[I]])->bool{let(A{m,n,..})=self; + impl PE<&[&[I]]> for A{fn eq(&self,r:&&[&[I]])->bool{ 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)}; @@ -121,7 +120,7 @@ use super::*; use std::marker::PhantomData as PD; /**monadic verbs*/impl A{ pub fn m_same(self)->R{Ok(self)} pub fn m_idot(self)->R{let(a@A{m,n,..})=self;let gi=|i,j|a.get(i,j)?.try_into().map_err(E::from); - if let(1,1)=(m,n){let(m,n)=(1,gi(1,1)?);let(mut o)=A::new(1,n)?; + if let(1,1)=(m,n){let(n)=(gi(1,1)?);let(mut o)=A::new(1,n)?; for(j)in(1..=n){o.set(1,j,(j-1).try_into()?)?;}Ok(unsafe{o.finish()})} else if let(1,2)=(m,n){let(m,n)=(gi(1,1)?,gi(1,2)?); let(mut v)=0_u32;let(f)=move |_,_|{let(v_o)=v;v+=1;Ok(v_o)};A::new(m,n)?.init_with(f)} @@ -136,9 +135,9 @@ use super::*; use std::marker::PhantomData as PD; /*return dyad function**/ pub fn f(&self)->fn(I,I)->I{use D::*; match(self){Plus=>D::add, Mul=>D::mul, Left=>D::left, Right=>D::right} } /*add two numbers*/fn add (x:I,y:I)->I{x+y} /*multiply two numbers*/fn mul (x:I,y:I)->I{x*y} - /*left */fn left(x:I,y:I)->I{x } /*right */fn right(x:I,y:I)->I{ y} + /*left */fn left(x:I,_:I)->I{x } /*right */fn right(_:I,y:I)->I{ y} } impl A{ - pub fn d_left (self,r:A)->R{Ok(self) } + pub fn d_left (self,_:A)->R{Ok(self) } pub fn d_right(self,r:A)->R{Ok(r) } pub fn d_plus(self,r:A) ->R{A::d_do(self,r,D::add)} pub fn d_mul (self,r:A) ->R{A::d_do(self,r,D::mul)} @@ -171,7 +170,7 @@ use super::*; use std::marker::PhantomData as PD; // === monadic `/`, `Ym::Insert` tests macro_rules! test_insert{($f:ident,$d:expr,$a:expr,$o:expr)=> {#[test]fn $f()->R<()>{let(a):R={$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())?; + 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, >::try_from(&[1,2,3,4,5]), (1+2+3+4+5) ); @@ -188,15 +187,14 @@ use super::*; use std::marker::PhantomData as PD; let f=|i,j|->R{let(x,y)=(l[i-1],r[j-1]);Ok(d(x,y))}; A::new(m,n)?.init_with(f)} else {bail!("unexpected fallthrough in Yd::table")}} - fn infix(d:D,l:A,r:A)->R{let(s)=r.as_slice().map_err(|_|err!("infix rhs must be a slice"))?; + fn infix(_:D,l:A,r:A)->R{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)]))}}} -/**deep-copy*/impl A{ - pub fn deep_copy(&self)->R{let A{m,n,l:li,d:di,i:_}=*self;A::new(m,n)?.init_with(|i,j|{self.get(i,j)})}} +/**deep-copy*/impl A{pub fn deep_copy(&self)->R{A::new(self.m,self.n)?.init_with(|i,j|{self.get(i,j)})}} /**display*/mod fmt{use super::*; impl DS for A{ - fn fmt(&self,fmt:&mut FMT)->FR{let A{m,n,..}=*self;for(i,j)in(self.iter()) + fn fmt(&self,fmt:&mut FMT)->FR{let A{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!()}}} diff --git a/src/j.rs b/src/j.rs index d0367e7..7c1e60c 100644 --- a/src/j.rs +++ b/src/j.rs @@ -1,4 +1,4 @@ -#![allow(unused_variables,unreachable_code,unused_imports,unused_parens)] +#![allow(unreachable_code,unused_imports,unused_parens)] /**prelude*/mod p;use p::*;#[cfg(test)]use p::tp::*; /**array*/mod a; /**read input*/mod r; /**symbol table*/mod s; pub use self::{a::*,r::*,s::*}; diff --git a/src/r.rs b/src/r.rs index de1e061..8c37721 100644 --- a/src/r.rs +++ b/src/r.rs @@ -98,8 +98,10 @@ mod lex{use crate::*; impl Ym{fn new(s:&str)->O{use Ym::*;Some(match s{"/" =>Insert,"\\"=>Prefix, _=>r!(None)})}} impl Yd{fn new(s:&str)->O{use Yd::*;Some(match s{"/" =>Table ,"\\"=>Infix , _=>r!(None)})}} #[cfg(test)]mod t{use super::*; - macro_rules! t{($f:ident,$i:literal)=>{#[test]fn $f()->R<()>{let(mut ts)=lex($i)?;let ast=parse(&mut ts)?;ok!()}}} - macro_rules! tf{($f:ident,$i:literal)=>{#[test] #[should_panic]fn $f(){let(mut ts)=lex($i).unwrap();let ast=parse(&mut ts).unwrap();}}} + macro_rules! t {($f:ident,$i:literal)=>{ + #[test] fn $f()->R<()>{let(mut ts)=lex($i)?; let _=parse(&mut ts)?;ok!()}}} + macro_rules! tf{($f:ident,$i:literal)=>{ + #[test] #[should_panic]fn $f() {let(mut ts)=lex($i).unwrap();let _=parse(&mut ts).unwrap();}}} /*parsing unit tests; t!(..) asserts a success, while tf asserts a failure.*/ t!(parse_1x1,"1"); t!(parse_1x3,"1 2 3"); t!(parse_tally_1,"# 1"); t!(parse_tally_1x3,"# 1 2 3"); From c14a5989fcb7416a16ba2466a51ff19815ee6721 Mon Sep 17 00:00:00 2001 From: katelyn martin Date: Thu, 23 Nov 2023 17:44:27 -0500 Subject: [PATCH 3/5] =?UTF-8?q?=E2=9C=8B=20fix=20=20lints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/j.rs | 2 +- src/r.rs | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/j.rs b/src/j.rs index 7c1e60c..b820ee0 100644 --- a/src/j.rs +++ b/src/j.rs @@ -1,4 +1,4 @@ -#![allow(unreachable_code,unused_imports,unused_parens)] +#![allow(unused_imports,unused_parens)] /**prelude*/mod p;use p::*;#[cfg(test)]use p::tp::*; /**array*/mod a; /**read input*/mod r; /**symbol table*/mod s; pub use self::{a::*,r::*,s::*}; diff --git a/src/r.rs b/src/r.rs index 8c37721..cb06619 100644 --- a/src/r.rs +++ b/src/r.rs @@ -54,7 +54,6 @@ mod lex{use crate::*; fn parse_(ts:&mut V,ctx:&mut V>)->R<()>{ // push a new AST node onto the `ctx` stack and return, indicating a successful parsing "step." macro_rules! step{($n:expr)=>{ctx.push(b!($n));r!(ok!());}} - let(v):S=match ts.pop(){ Some(T::V(v)) =>v, /*take the next verb, or return if done*/ None=>r!(ok!()), Some(T::A(v)) =>{let(n)=v.try_into()?;step!(n);} // array literal @@ -70,7 +69,6 @@ mod lex{use crate::*; /*first, process monadic and dyadic verbs*/ if let Some(l)=lhs{let(d)=D::new(&v).ok_or(err!("invalid dyad {v:?}"))?;step!(N::D{l,r:rhs,d});} else if let Some(m)=M::new(&v){step!(N::M{m,o:rhs});} - /*otherwise, we should treat this as an adverb*/ let(y)=v;let(d)=ts.pop().ok_or(err!("adverbs need a verb to apply"))?; macro_rules! ym {()=>{ @@ -87,9 +85,7 @@ mod lex{use crate::*; /*monadic adverb*/ /*dyadic adverb */ None =>{ ym!();} Some(T::A(v)) =>{let(l)=b!(v.try_into()?);yd!(l);} Some(t@T::E|t@T::V(_))=>{ts.push(t);ym!();} Some(T::SY(sy))=>{let(l)=b!(sy.into()); yd!(l);} - } - bail!("fallthrough: unexpected parsing error");} - + }} impl M {fn new(s:&str)->O {use M::*; Some(match s{"i."=>Idot ,"$" =>Shape ,"|:"=>Transpose , "#" =>Tally ,"[" =>Same ,"]" =>Same , ">:"=>Inc, _=>r!(None)})}} From c49b68945a099d8d991c2823e1d83d14c22cc07f Mon Sep 17 00:00:00 2001 From: katelyn martin Date: Thu, 23 Nov 2023 17:49:58 -0500 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=99=82=20finish=20up=20lints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/j.rs | 7 +++---- src/p.rs | 2 +- src/r.rs | 6 +++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/j.rs b/src/j.rs index b820ee0..c72de17 100644 --- a/src/j.rs +++ b/src/j.rs @@ -1,7 +1,6 @@ -#![allow(unused_imports,unused_parens)] -/**prelude*/mod p;use p::*;#[cfg(test)]use p::tp::*; -/**array*/mod a; /**read input*/mod r; /**symbol table*/mod s; -pub use self::{a::*,r::*,s::*}; +#![allow(unused_parens)] /**prelude*/mod p;use p::*; /*test prelude*/#[cfg(test)]use p::tp::*; + /**symbol table*/mod s; /**array*/ mod a; /**lex/parse input*/mod r;use r::*; +pub use self::{a::*,s::*}; pub fn eval(input:&str,st:&mut ST)->R>{ let(mut ts)=lex(input)?;let(ast)=match(parse(&mut ts)?){Some(x)=>x,None=>rrn!()};eval_(ast,st)} fn eval_(ast:B,st:&mut ST)->R>{use{M::*,D::*}; diff --git a/src/p.rs b/src/p.rs index 2aa0471..844c5ff 100644 --- a/src/p.rs +++ b/src/p.rs @@ -1,4 +1,4 @@ -//! prelude; shorthand aliases for common types and traits, macros for common patterns. +#![allow(unused_imports)] //! prelude; shorthand aliases for common types and traits, macros for common patterns. pub(crate)use{Box as B,char as C,u32 as I,usize as U,Option as O,String as S,TryFrom as TF,TryInto as TI,Vec as V}; pub(crate)use{std::{alloc::Layout as L,clone::Clone as CL,cmp::{PartialEq as PE,PartialOrd as PO}, collections::{BTreeMap as BM,VecDeque as VD},fmt::{Debug as DBG,Display as DS,Formatter as FMT,Result as FR}, diff --git a/src/r.rs b/src/r.rs index cb06619..ca4fa66 100644 --- a/src/r.rs +++ b/src/r.rs @@ -4,7 +4,7 @@ mod lex{use crate::*; /*assignment*/ E , /* NB: this does not identify whether possible verbs */ /*(ad)verb*/ V(S) , /* are monadic or dyadic. that is done during parsing.*/ /*symbol*/ SY(SY) } - pub(crate) fn lex(input:&str)->R>{use std::ops::Deref; + pub(crate) fn lex(input:&str)->R>{ let(mut ts)=input.split_whitespace().peekable(); let(mut o)=V::with_capacity(ts.size_hint().0); while let Some(t) =ts.next(){ if t == "=:" {o.push(T::E)} // assignment @@ -15,7 +15,7 @@ mod lex{use crate::*; while let Some(i)=peek!(){put!(i);} o.push(T::A(v));} else {o.push(T::V(S::from(t)))} // otherwise, a verb or adverb } r!(Ok(o)) } - #[cfg(test)]mod t{use super::{*,T::A as TA,T::V as TV,T::SY as TSY}; + #[cfg(test)]mod t{use super::{*,T::A as TA,T::V as TV}; /// test helper: lex an expression and check the output macro_rules! t{($f:ident,$i:literal,$o:expr)=>{#[test]fn $f()->R<()>{eq!(lex($i)?,$o);ok!()}}} macro_rules! sy{($i:literal)=>{$i.parse().map(T::SY).unwrap()}} @@ -30,7 +30,7 @@ mod lex{use crate::*; t!(lex_symbol, "abc", v![sy!("abc")] ); t!(lex_assign, "a =: 1", v![sy!("a"), T::E, TA(v![1])] ); } -}/**input parsing*/mod parse{use {crate::*,super::lex::{T,lex}}; +}/**input parsing*/mod parse{use {crate::*,super::lex::T}; /**dyadic verb */ #[derive(DBG,PE,PO)] pub enum D {Plus,Mul, Left, Right } /**monadic verb */ #[derive(DBG,PE,PO)] pub enum M {Idot,Shape,Tally,Transpose,Same,Inc} /**dyadic adverb */ #[derive(DBG )] pub enum Yd{/**dyadic `/` */ Table , From cb4a07abb2e217c1797208826e1f827903778eaf Mon Sep 17 00:00:00 2001 From: katelyn martin Date: Thu, 23 Nov 2023 18:35:53 -0500 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=92=90=20polish=20the=20main=20loop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 ++++++++++++++++ src/x.rs | 15 +++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5cf1bed..934699f 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,22 @@ voice feels like, and why people do it. #### 🐣 j +**🔁 main loop** + +above we looked at the Incunabulum's main event loop. here is j's equivalent entrypoint: + +```rust +mod p;use{p::*,j::*,std::io::Write}; +fn main()->R<()>{let mut st=ST::default(); // define symbol table + let prompt =| |{print!(" ");std::io::stdout().flush()?;ok!()}; // (callback) print whitespace + let read =|_ |{let mut l=S::new();stdin().read_line(&mut l)?;Ok(l)}; // (callback) read input + let mut eval=|s:S|{eval(&s,&mut st)}; // (callback) read and evaluate once + let print =|a:A|{println!("{a}")}; // (callback) print array + loop{prompt().and_then(read).and_then(&mut eval)?.map(print);}; /* !!! main event loop !!! */ } +``` + +**🏃 verbs** + the core of the four dyadic verbs `[`, `]`, `+`, and `*` is shown below. the definitions of the `A` array type and the `D` dyadic verb enum are included for reference. diff --git a/src/x.rs b/src/x.rs index b23a7d7..ca302ca 100644 --- a/src/x.rs +++ b/src/x.rs @@ -1,6 +1,9 @@ -//! a J interpreter fragment, implemented in Rust. -#![allow(dead_code,unused_variables,unreachable_code,unused_imports,unused_parens)] -mod p; use{p::*,j::*}; fn main()->R<()>{use std::io::Write;let(mut st)=ST::default(); - let(pr)=||{print!(" ");std::io::stdout().flush()}; - let(rl)=||{let(mut l)=S::new();stdin().read_line(&mut l)?;Ok::<_,E>(l)};let(mut ev)=|l:S|eval(&l,&mut st); - loop{pr()?;let(o)=rl().and_then(|l|ev(l))?;if let Some(o)=o{println!("{}",o)}}ur!();} +/**a J interpreter fragment, implemented in Rust.*/ +mod p;use{p::*,j::*,std::io::Write}; +/// main interpreter entrypoint and event-loop. +fn main()->R<()>{let mut st=ST::default(); // define symbol table + let prompt =| |{print!(" ");std::io::stdout().flush()?;ok!()}; // (callback) print whitespace + let read =|_ |{let mut l=S::new();stdin().read_line(&mut l)?;Ok(l)}; // (callback) read input + let mut eval=|s:S|{eval(&s,&mut st)}; // (callback) read and evaluate once + let print =|a:A|{println!("{a}")}; // (callback) print array + loop{prompt().and_then(read).and_then(&mut eval)?.map(print);}; /* !!! main event loop !!! */ }