From d75add5ea32806a1238140c0dafd13f9c36cb005 Mon Sep 17 00:00:00 2001 From: Lawrence Bethlenfalvy Date: Tue, 21 Feb 2023 18:10:39 +0000 Subject: [PATCH] transfer commit --- .editorconfig | 18 ++++++++++ src/executor/mod.rs | 7 ++-- src/executor/reduction_tree.rs | 5 +++ src/executor/syntax_eq.rs | 6 ++++ src/main.rs | 2 +- src/representations/ast_to_typed.rs | 32 ++++++++--------- src/representations/typed.rs | 4 ++- src/scheduler/mod.rs | 2 +- src/scheduler/task_pair.rs | 55 ++++++++++++++++++++--------- src/scheduler/task_vec.rs | 50 ++++++++++++++++++++++---- 10 files changed, 135 insertions(+), 46 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d3af585 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Set default charset +[*.{rs,md,toml,orc,tex,bib}] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 2 + +[Makefile] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_styl = tab \ No newline at end of file diff --git a/src/executor/mod.rs b/src/executor/mod.rs index d81d733..bc76c6f 100644 --- a/src/executor/mod.rs +++ b/src/executor/mod.rs @@ -1,8 +1,5 @@ -mod foreign; -// mod normalize; +mod normalize; mod partial_hash; mod reduction_tree; mod apply_lambda; -mod syntax_eq; -pub use foreign::ExternFn; -pub use foreign::Atom; \ No newline at end of file +mod syntax_eq; \ No newline at end of file diff --git a/src/executor/reduction_tree.rs b/src/executor/reduction_tree.rs index 8c9f32d..e367142 100644 --- a/src/executor/reduction_tree.rs +++ b/src/executor/reduction_tree.rs @@ -95,3 +95,8 @@ fn direct_reductions(ex: Mrc) -> impl Iterator> { }) } +/* + + + + */ \ No newline at end of file diff --git a/src/executor/syntax_eq.rs b/src/executor/syntax_eq.rs index b95179d..337fa32 100644 --- a/src/executor/syntax_eq.rs +++ b/src/executor/syntax_eq.rs @@ -64,6 +64,12 @@ impl Context { }) } + fn unify_clauses(&mut self, + left: &Mrc<[Clause]>, right: &Mrc<[Clause]>, lambdas: LambdaMap + ) -> Result, UnifError> { + if left.len() != right.len() {return Err(UnifError::Conflict)} + } + fn unify_clause(&mut self, left: &Clause, right: &Clause, lambdas: LambdaMap ) -> Result, UnifError> { diff --git a/src/main.rs b/src/main.rs index f4e51e7..99ae0f1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use std::env::current_dir; -// mod executor; +mod executor; mod parse; mod project; mod utils; diff --git a/src/representations/ast_to_typed.rs b/src/representations/ast_to_typed.rs index 25fd769..95c5649 100644 --- a/src/representations/ast_to_typed.rs +++ b/src/representations/ast_to_typed.rs @@ -49,9 +49,9 @@ pub fn exprv(exprv: &[ast::Expr]) -> Result { const NAMES_INLINE_COUNT:usize = 3; /// Recursive state of [exprv] -fn exprv_rec( - v: &[ast::Expr], - names: ProtoMap<&str, (u64, bool), NAMES_INLINE_COUNT>, +fn exprv_rec<'a>( + v: &'a [ast::Expr], + names: ProtoMap<&'a str, (u64, bool), NAMES_INLINE_COUNT>, explicits: Option<&Stackframe>>, ) -> Result<(typed::Expr, usize), Error> { let (last, rest) = v.split_last().ok_or(Error::EmptyS)?; @@ -61,12 +61,12 @@ fn exprv_rec( "It is assumed that Explicit nodes can never have type annotations as the \ wrapped expression node matches all trailing colons." ); - let (x, _) = expr_rec(inner.as_ref(), names, None)?; - let new_explicits = Some(&Stackframe::opush(explicits, Mrc::new(x))); - let (body, used_expls) = exprv_rec(rest, names, new_explicits)?; + let (x, _) = expr_rec(inner.as_ref(), names.clone(), None)?; + let new_explicits = Stackframe::opush(explicits, Mrc::new(x)); + let (body, used_expls) = exprv_rec(rest, names, Some(&new_explicits))?; Ok((body, used_expls.saturating_sub(1))) } else { - let (f, f_used_expls) = exprv_rec(rest, names, explicits)?; + let (f, f_used_expls) = exprv_rec(rest, names.clone(), explicits)?; let x_explicits = Stackframe::opop(explicits, f_used_expls); let (x, x_used_expls) = expr_rec(last, names, x_explicits)?; Ok((typed::Expr( @@ -77,13 +77,13 @@ fn exprv_rec( } /// Recursive state of [expr] -fn expr_rec( - ast::Expr(val, typ): &ast::Expr, - names: ProtoMap<&str, (u64, bool), NAMES_INLINE_COUNT>, +fn expr_rec<'a>( + ast::Expr(val, typ): &'a ast::Expr, + names: ProtoMap<&'a str, (u64, bool), NAMES_INLINE_COUNT>, explicits: Option<&Stackframe>> // known explicit values ) -> Result<(typed::Expr, usize), Error> { // (output, used_explicits) let typ: Vec = typ.iter() - .map(|c| Ok(clause_rec(c, names, None)?.0)) + .map(|c| Ok(clause_rec(c, names.clone(), None)?.0)) .collect::>()?; if let ast::Clause::S(paren, body) = val { if *paren != '(' {return Err(Error::BadGroup(*paren))} @@ -101,9 +101,9 @@ fn expr_rec( } /// Recursive state of [clause] -fn clause_rec( - cls: &ast::Clause, - names: ProtoMap<&str, (u64, bool), NAMES_INLINE_COUNT>, +fn clause_rec<'a>( + cls: &'a ast::Clause, + mut names: ProtoMap<&'a str, (u64, bool), NAMES_INLINE_COUNT>, mut explicits: Option<&Stackframe>> ) -> Result<(typed::Clause, usize), Error> { match cls { // (\t:(@T. Pair T T). t \left.\right. left) @number -- this will fail @@ -121,7 +121,7 @@ fn clause_rec( explicits = rest_explicits; // Convert the type let typ = if t.len() == 0 {mrc_empty_slice()} else { - let (typed::Expr(c, t), _) = exprv_rec(t.as_ref(), names, None)?; + let (typed::Expr(c, t), _) = exprv_rec(t.as_ref(), names.clone(), None)?; if t.len() > 0 {return Err(Error::ExplicitBottomKind)} else {one_mrc_slice(c)} }; @@ -143,7 +143,7 @@ fn clause_rec( let id = get_name(); // Convert the type let typ = if t.len() == 0 {mrc_empty_slice()} else { - let (typed::Expr(c, t), _) = exprv_rec(t.as_ref(), names, None)?; + let (typed::Expr(c, t), _) = exprv_rec(t.as_ref(), names.clone(), None)?; if t.len() > 0 {return Err(Error::ExplicitBottomKind)} else {one_mrc_slice(c)} }; diff --git a/src/representations/typed.rs b/src/representations/typed.rs index 8200fb6..bde1b24 100644 --- a/src/representations/typed.rs +++ b/src/representations/typed.rs @@ -136,4 +136,6 @@ impl TryFrom<&ast::Clause> for Clause { fn try_from(value: &ast::Clause) -> Result { ast_to_typed::clause(value) } -} \ No newline at end of file +} + +pub fn count_references(id: u64, clause: &Clause) \ No newline at end of file diff --git a/src/scheduler/mod.rs b/src/scheduler/mod.rs index bcc5818..afef8cb 100644 --- a/src/scheduler/mod.rs +++ b/src/scheduler/mod.rs @@ -25,7 +25,7 @@ pub trait Task { } fn run_to_completion(&mut self) -> Self::Result { - loop { if let TaskState::Complete(r) = self.run_once() {return r} } + loop { if let TaskState::Complete(r) = self.run_n_times(u64::MAX) {return r} } } fn boxed<'a>(self) -> TaskBox<'a, Self::Result> where Self: 'a + Sized { Box::new(self) } diff --git a/src/scheduler/task_pair.rs b/src/scheduler/task_pair.rs index 373b9c9..8f23cbf 100644 --- a/src/scheduler/task_pair.rs +++ b/src/scheduler/task_pair.rs @@ -26,42 +26,65 @@ impl TaskPair { } } -impl Task for TaskPair { - type Result = (T::Result, U::Result); - - fn run_once(&mut self) -> TaskState { - let TaskPair{ state, tally, l_nice, r_nice } = self; +/// The state machine logic, abstracted from the subtask handling system +macro_rules! main_logic { + ($self:ident, $task:ident, $task_runner:expr) => {{ + let TaskPair{ state, tally, l_nice, r_nice } = $self; let ret = process(state, |s| match s { TaskPairState::Empty => panic!("Generator completed and empty"), - TaskPairState::Left(mut l_task, r_res) => { - match l_task.run_once() { + TaskPairState::Left(mut $task, r_res) => { + match $task_runner { TaskState::Complete(r) => (TaskPairState::Empty, TaskState::Complete((r, r_res))), - TaskState::Yield => (TaskPairState::Left(l_task, r_res), TaskState::Yield), + TaskState::Yield => (TaskPairState::Left($task, r_res), TaskState::Yield), } } - TaskPairState::Right(l_res, mut r_task) => { - match r_task.run_once() { + TaskPairState::Right(l_res, mut $task) => { + match $task_runner { TaskState::Complete(r) => (TaskPairState::Empty, TaskState::Complete((l_res, r))), - TaskState::Yield => (TaskPairState::Right(l_res, r_task), TaskState::Yield), + TaskState::Yield => (TaskPairState::Right(l_res, $task), TaskState::Yield), } } - TaskPairState::Both(mut l_task, mut r_task) => { + TaskPairState::Both(l_task, r_task) => { let state = if 0 <= *tally { *tally -= *l_nice as Priority; - match l_task.run_once() { + let mut $task = l_task; + match $task_runner { TaskState::Complete(r) => TaskPairState::Right(r, r_task), - TaskState::Yield => TaskPairState::Both(l_task, r_task), + TaskState::Yield => TaskPairState::Both($task, r_task), } } else { *tally += *r_nice as Priority; - match r_task.run_once() { + let mut $task = r_task; + match $task_runner { TaskState::Complete(r) => TaskPairState::Left(l_task, r), - TaskState::Yield => TaskPairState::Both(l_task, r_task), + TaskState::Yield => TaskPairState::Both(l_task, $task), } }; (state, TaskState::Yield) } }); ret + }}; +} + +impl Task for TaskPair { + type Result = (T::Result, U::Result); + + fn run_n_times(&mut self, mut count: u64) -> TaskState { + loop { + if count == 0 {return TaskState::Yield} + match self.state { + TaskPairState::Left(..) | TaskPairState::Right(..) => { + return main_logic!(self, task, task.run_n_times(count)); + } + _ => () + } + if let r@TaskState::Complete(_) = self.run_once() {return r} + count -= 1; + } + } + + fn run_once(&mut self) -> TaskState { + main_logic!(self, task, task.run_once()) } } diff --git a/src/scheduler/task_vec.rs b/src/scheduler/task_vec.rs index 7aceeda..198295a 100644 --- a/src/scheduler/task_vec.rs +++ b/src/scheduler/task_vec.rs @@ -1,4 +1,4 @@ -use std::iter; +use std::{iter, mem}; use itertools::Itertools; @@ -36,8 +36,9 @@ impl TaskVec { if self.task_heap.len() <= i {None} else {self.task_heap[i].as_mut()} } + /// Returns the tally of the given record. Empty records always sink to the bottom fn tally(&self, i: usize) -> Nice { - self.task_heap[i].as_ref().map(|e| e.tally).unwrap_or(0) + self.task_heap[i].as_ref().map(|e| e.tally).unwrap_or(Nice::MAX) } fn swap(&mut self, a: usize, b: usize) { self.task_heap.swap(a, b); @@ -49,7 +50,7 @@ impl TaskVec { fn normalize(&mut self) { let shrink_count = self.task_heap.iter().rev().take_while(|e| e.is_none()).count(); let new_len = self.task_heap.len() - shrink_count; - self.task_heap.splice(0..new_len, iter::empty()); + self.task_heap.splice(new_len.., iter::empty()); let head = self.entry_mut(0); let offset = if let Some(e) = head { let offset = e.tally - 1; @@ -86,10 +87,43 @@ impl TaskVec { self.swap(i, mchi); self.sink(mchi); } + + fn take_results(&mut self) -> Vec { + let mut swap = Vec::new(); + mem::swap(&mut self.results, &mut swap); + return swap.into_iter().collect::>() + .expect("Results not full but the heap is empty"); + } + + fn one_left(&mut self) -> bool { + self.entry(0).is_some() && self.entry(1).is_none() && self.entry(2).is_none() + } } impl Task for TaskVec { + type Result = Vec; + + fn run_n_times(&mut self, mut count: u64) -> TaskState { + loop { + if count == 0 {return TaskState::Yield} + if self.one_left() { + let head = &mut self.task_heap[0]; + let head_entry = head.as_mut().expect("one_left faulty"); + return match head_entry.task.run_n_times(count) { + TaskState::Yield => TaskState::Yield, + TaskState::Complete(r) => { + self.results[head_entry.position] = Some(r); + *head = None; + return TaskState::Complete(self.take_results()); + } + } + } else if let r@TaskState::Complete(_) = self.run_once() {return r} + count -= 1; + } + } + fn run_once(&mut self) -> super::TaskState { + self.normalize(); let head = &mut self.task_heap[0]; let head_entry = head.as_mut().expect("All completed, cannot run further"); head_entry.tally += head_entry.nice; @@ -98,9 +132,13 @@ impl Task for TaskVec { self.results[head_entry.position] = Some(r); *head = None; self.sink(0); - if self.entry(0).is_some() { - - } + if self.entry(0).is_some() { return TaskState::Yield } + TaskState::Complete(self.take_results()) + } + TaskState::Yield => { + head_entry.tally += head_entry.nice; + self.sink(0); + TaskState::Yield } } }