From df339bbbe822251050d1c29033e98615afafbc0e Mon Sep 17 00:00:00 2001 From: Dima Korolev Date: Sat, 31 May 2025 16:11:15 -0700 Subject: [PATCH 1/9] Guarded the debug output. --- step11_ws_state_machine/code/src/main.rs | 40 +++++++++++++++--------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/step11_ws_state_machine/code/src/main.rs b/step11_ws_state_machine/code/src/main.rs index c1d9f03..e6d0432 100644 --- a/step11_ws_state_machine/code/src/main.rs +++ b/step11_ws_state_machine/code/src/main.rs @@ -18,6 +18,12 @@ use tokio::{ sync::{Mutex, mpsc}, }; +#[cfg(test)] +const DEBUG_MAROON_STATE_DUMP: bool = true; + +#[cfg(not(test))] +const DEBUG_MAROON_STATE_DUMP: bool = false; + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] struct LogicalTimeAbsoluteMs(u64); @@ -886,18 +892,20 @@ async fn execute_pending_operations_inner(state: &mut Arc { - let n = maroon_task_state_local_vars_count(&s); - println!(" state: {s:?}, uses {n} argument(s) above as its local stack."); - } - MaroonTaskStackEntry::Retrn(r) => { - println!(" retrn: {r:?}, awaiting to be `return`-ed into here."); - } - MaroonTaskStackEntry::Value(v) => { - println!(" value: {v:?}"); + if DEBUG_MAROON_STATE_DUMP { + println!("MAROON STEP AT T={scheduled_timestamp}ms"); + for e in &maroon_task.maroon_stack.maroon_stack_entries { + match e { + MaroonTaskStackEntry::State(s) => { + let n = maroon_task_state_local_vars_count(&s); + println!(" state: {s:?}, uses {n} argument(s) above as its local stack."); + } + MaroonTaskStackEntry::Retrn(r) => { + println!(" retrn: {r:?}, awaiting to be `return`-ed into here."); + } + MaroonTaskStackEntry::Value(v) => { + println!(" value: {v:?}"); + } } } } @@ -928,7 +936,9 @@ async fn execute_pending_operations_inner(state: &mut Arc { fsm.active_tasks.remove(&task_id); @@ -978,7 +988,9 @@ async fn execute_pending_operations_inner(state: &mut Arc Date: Sat, 31 May 2025 16:31:19 -0700 Subject: [PATCH 2/9] Validating the stack, no longer `unused_`, called everywhere. --- step11_ws_state_machine/code/src/main.rs | 73 ++++++++++++++---------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/step11_ws_state_machine/code/src/main.rs b/step11_ws_state_machine/code/src/main.rs index e6d0432..0d1c23b 100644 --- a/step11_ws_state_machine/code/src/main.rs +++ b/step11_ws_state_machine/code/src/main.rs @@ -228,9 +228,7 @@ enum MaroonTaskStackEntryValue { FactorialReturnValue(u64), } -// For a given state, how many entries on the maroon stack right below ("above") this state are its stack variables. -// TODO(dkorolev): For now we can (should?) example the contents of the stack manually, this is not done yet. -// NOTE(dkorolev): Can probably be done better wrt encoding which types they should be, not just the count. +// For a given `S`, if the maroon stack contains `State(S)`, how many entries above it are its local stack vars. const fn maroon_task_state_local_vars_count(e: &MaroonTaskState) -> usize { match e { MaroonTaskState::FactorialEntry => 1, // [FactorialInput] @@ -243,6 +241,15 @@ const fn maroon_task_state_local_vars_count(e: &MaroonTaskState) -> usize { } } +// For a given `S`, if the maroon stack contains `Retrn(S)`, how many entries above it are its local stack vars. +const fn maroon_task_state_return_local_vars_count(e: &MaroonTaskState) -> usize { + match e { + MaroonTaskState::FactorialDone => 1, // [FactorialInput] + MaroonTaskState::FactorialRecursionPostRecursiveCall => 1, // [FactorialArgument] + _ => 0, + } +} + // NOTE(dkorolev): The convention so far is the following: // * The "last" element of the stack is the state of the task. // * It is known up front how many entries before this state are its "local variables", including parameters. @@ -842,35 +849,40 @@ async fn execute_pending_operations(mut state: Arc) { - let n = new_states_vec.len(); - if n == 0 { - panic!("In `validate_states_vec_or_panic` the `new_states_vec` should not be empty."); +fn debug_validate_maroon_stack(stk: &Vec) { + let stack_depth = stk.len(); + if stack_depth == 0 { + panic!("In `debug_validate_maroon_stack` the `stk` should not be empty."); } else { - if let MaroonTaskStackEntry::State(new_state) = &new_states_vec[0] { - if n != maroon_task_state_local_vars_count(&new_state) + 1 { - panic!( - "In `validate_states_vec_or_panic` expecting {} arguments for state {new_state:?}, seeing {}.", - maroon_task_state_local_vars_count(&new_state), - n - 1 - ); + let mut i = stack_depth - 1; + while i > 0 { + let n = { + if let MaroonTaskStackEntry::State(state) = &stk[i] { + maroon_task_state_local_vars_count(&state) + } else if let MaroonTaskStackEntry::Retrn(state) = &stk[i] { + maroon_task_state_return_local_vars_count(&state) + } else { + panic!("In `debug_validate_maroon_stack` the `stk[0]` should be a state, not {:?}.", stk[i]); + } + }; + if n > i { + let state = &stk[i]; + panic!("In `debug_validate_maroon_stack` expecting {n} arguments for state {state:?}, only have {i} left.",); } - for i in 1..n { - if let MaroonTaskStackEntry::Value(_) = &new_states_vec[i] { + for _ in 0..n { + i = i - 1; + if let MaroonTaskStackEntry::Value(value) = &stk[i] { // OK } else { - panic!( - "In `validate_states_vec_or_panic` expecting value, for non-value, pls examine `{:?}`.", - new_states_vec - ); + panic!("In `debug_validate_maroon_stack` expecting value, for non-value, pls examine `{:?}`.", stk); } } - } else { - panic!( - "In `validate_states_vec_or_panic` the `new_states_vec[0]` should not a state, not {:?}.", - new_states_vec[0] - ); + if i == 0 { + // All good, traversed the entire stack, which was not empty at the beginning of the call, no issues found. + break; + } else { + i = i - 1 + } } } } @@ -910,6 +922,9 @@ async fn execute_pending_operations_inner(state: &mut Arc(state: &mut Arc { - // unused_validate_states_vec_or_panic(&new_states_vec); for new_state in new_states_vec.into_iter() { maroon_task.maroon_stack.maroon_stack_entries.push(new_state); } + debug_validate_maroon_stack(&maroon_task.maroon_stack.maroon_stack_entries); let scheduled_timestamp = scheduled_timestamp + sleep_ms; fsm.active_tasks.insert(task_id, maroon_task); fsm.pending_operations.push(TimestampedMaroonTask::new(scheduled_timestamp, task_id)); } MaroonStepResult::Write(text, new_states_vec) => { - // unused_validate_states_vec_or_panic(&new_states_vec); let _ = maroon_task.writer.write_text(text, Some(scheduled_timestamp)).await; for new_state in new_states_vec.into_iter() { maroon_task.maroon_stack.maroon_stack_entries.push(new_state); } + debug_validate_maroon_stack(&maroon_task.maroon_stack.maroon_stack_entries); fsm.active_tasks.insert(task_id, maroon_task); fsm.pending_operations.push(TimestampedMaroonTask::new(scheduled_timestamp, task_id)); } MaroonStepResult::Next(new_states_vec) => { - // unused_validate_states_vec_or_panic(&new_states_vec); for new_state in new_states_vec.into_iter() { maroon_task.maroon_stack.maroon_stack_entries.push(new_state); } + debug_validate_maroon_stack(&maroon_task.maroon_stack.maroon_stack_entries); fsm.active_tasks.insert(task_id, maroon_task); fsm.pending_operations.push(TimestampedMaroonTask::new(scheduled_timestamp, task_id)); } From 6aa9d5f1da320dd4428a64d2e66541d741a3ca2c Mon Sep 17 00:00:00 2001 From: Dima Korolev Date: Sat, 31 May 2025 16:32:26 -0700 Subject: [PATCH 3/9] Only validating the stack in `test` builds. --- step11_ws_state_machine/code/src/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/step11_ws_state_machine/code/src/main.rs b/step11_ws_state_machine/code/src/main.rs index 0d1c23b..ab9fe86 100644 --- a/step11_ws_state_machine/code/src/main.rs +++ b/step11_ws_state_machine/code/src/main.rs @@ -849,6 +849,7 @@ async fn execute_pending_operations(mut state: Arc) { let stack_depth = stk.len(); if stack_depth == 0 { @@ -887,6 +888,9 @@ fn debug_validate_maroon_stack(stk: &Vec) { } } +#[cfg(not(test))] +fn debug_validate_maroon_stack(_: &Vec) {} + async fn execute_pending_operations_inner(state: &mut Arc>) { loop { let mut fsm = state.fsm.lock().await; From 9fc2346a6805dbcf447da1623372b3a6237d49e4 Mon Sep 17 00:00:00 2001 From: Dima Korolev Date: Sat, 31 May 2025 16:53:18 -0700 Subject: [PATCH 4/9] Re-added back the `/delay/` handler, with the stack. --- step11_ws_state_machine/code/src/main.rs | 103 ++++++++++------------- 1 file changed, 45 insertions(+), 58 deletions(-) diff --git a/step11_ws_state_machine/code/src/main.rs b/step11_ws_state_machine/code/src/main.rs index ab9fe86..d2c63f4 100644 --- a/step11_ws_state_machine/code/src/main.rs +++ b/step11_ws_state_machine/code/src/main.rs @@ -187,8 +187,6 @@ impl Writer for WebSocketWriter { enum MaroonTaskState { Completed, /* - DelayedMessageTaskBegin, - DelayedMessageTaskExecute, DivisorsTaskBegin, DivisorsTaskIteration, DivisorsPrintAndMoveOn, @@ -197,6 +195,8 @@ enum MaroonTaskState { FibonacciTaskResult, FibonacciTaskStep, */ + DelayedMessageTaskBegin, + DelayedMessageTaskExecute, FactorialEntry, FactorialRecursiveCall, FactorialRecursionPostWrite, @@ -205,24 +205,12 @@ enum MaroonTaskState { FactorialDone, } -/* -// TODO(dkorolev): This `MaroonTaskRuntime` will soon be deprecated. Everything will be of "state" `Generic` first, -// and then `TaskRuntime` will no longer be needed, in favor of "passive" (stateless) "state" as a plain enum, -// plus the [maroon] stack, plus the [maroon] heap. -// TODO(dkorolev): In this commit, refactoring begins with Factorial. -#[derive(Debug)] -enum MaroonTaskRuntime { - Generic, - DelayedMessage(MaroonTaskRuntimeDelayedMessage), - Divisors(MaroonTaskRuntimeDivisors), - Fibonacci(MaroonTaskRuntimeFibonacci), -} -*/ - // NOTE(dkorolev): These dedicated types are easier for manual development. // NOTE(dkorolev): They will all be "type-erased" later on, esp. once we get to the DSL part. #[derive(Debug, Clone)] enum MaroonTaskStackEntryValue { + DelayInputMs(u64), + DelayInputMessage(String), // TODO(dkorolev): This `String` contradicts the `u64` promise, but not really. FactorialInput(u64), FactorialArgument(u64), FactorialReturnValue(u64), @@ -237,6 +225,8 @@ const fn maroon_task_state_local_vars_count(e: &MaroonTaskState) -> usize { MaroonTaskState::FactorialRecursionPostSleep => 1, // [FactorialArgument] MaroonTaskState::FactorialRecursionPostRecursiveCall => 2, // [FactorialArgument, FactorialReturnValue] MaroonTaskState::FactorialDone => 2, // [FactorialInput, FactorialReturnValue] + MaroonTaskState::DelayedMessageTaskBegin => 2, // [DelayInputMs, DelayInputMessage] + MaroonTaskState::DelayedMessageTaskExecute => 2, // [DelayInputMs, DelayInputMessage] _ => 0, } } @@ -279,12 +269,6 @@ impl MaroonTaskHeap { } /* -#[derive(Clone, Debug)] -struct MaroonTaskRuntimeDelayedMessage { - delay: LogicalTimeAbsoluteMs, - message: String, -} - #[derive(Clone, Debug)] struct MaroonTaskRuntimeDivisors { n: u64, @@ -363,27 +347,42 @@ enum MaroonStepResult { fn global_step(state: MaroonTaskState, vars: Vec) -> MaroonStepResult { match state { - /* MaroonTaskState::DelayedMessageTaskBegin => { - if let MaroonTaskRuntime::DelayedMessage(data) = runtime { - MaroonStepResult::Sleep( - LogicalTimeDeltaMs::from_millis(data.delay.as_millis()), - vec![MaroonTaskStackEntry::State(MaroonTaskState::DelayedMessageTaskExecute)], - ) + if let Some(MaroonTaskStackEntryValue::DelayInputMessage(msg)) = vars.get(0) { + if let Some(MaroonTaskStackEntryValue::DelayInputMs(delay_ms)) = vars.get(1) { + let delay_ms = *delay_ms; + let msg = msg.clone(); + MaroonStepResult::Sleep( + LogicalTimeDeltaMs::from_millis(delay_ms), + vec![ + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMs(delay_ms)), + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMessage(msg)), + MaroonTaskStackEntry::State(MaroonTaskState::DelayedMessageTaskExecute), + ], + ) + } else { + panic!("Unexpected argument 1 type in `DelayedMessageTaskBegin`: `{:?}`.", vars.get(1)); + } } else { - panic!("Runtime type mismatch for `DelayedMessageTaskBegin`."); + panic!("Unexpected argument 0 type in `DelayedMessageTaskBegin`: `{:?}`.", vars.get(0)); } } MaroonTaskState::DelayedMessageTaskExecute => { - if let MaroonTaskRuntime::DelayedMessage(data) = runtime { - MaroonStepResult::Write( - format_delayed_message(data.delay, &data.message), - vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)], - ) + if let Some(MaroonTaskStackEntryValue::DelayInputMessage(msg)) = vars.get(0) { + if let Some(MaroonTaskStackEntryValue::DelayInputMs(delay_ms)) = vars.get(1) { + let delay_ms = *delay_ms; + MaroonStepResult::Write( + format_delayed_message(LogicalTimeAbsoluteMs::from_millis(delay_ms), msg), + vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)], + ) + } else { + panic!("Unexpected argument 1 type in `DelayedMessageTaskExecute`: `{:?}`.", vars.get(1)); + } } else { - panic!("Runtime type mismatch for `DelayedMessageTaskExecute`."); + panic!("Unexpected argument 0 type in `DelayedMessageTaskExecute`: `{:?}`.", vars.get(0)); } } + /* MaroonTaskState::DivisorsTaskBegin => { if let MaroonTaskRuntime::Divisors(data) = runtime { data.i = data.n; @@ -694,31 +693,25 @@ async fn ackermann_handler_ws(socket: WebSocket, m: i64, n: i64, _stat let _ = async_ack(Arc::new(WebSocketWriter::new(socket)), m, n, 0).await; } -/* async fn delay_handler( - ws: WebSocketUpgrade, - Path((t, s)): Path<(u64, String)>, - State(state): State>>, + ws: WebSocketUpgrade, Path((t, s)): Path<(u64, String)>, State(state): State>>, ) -> impl IntoResponse { ws.on_upgrade(move |socket| delay_handler_ws(socket, state.timer.millis_since_start(), t, s, state)) } async fn delay_handler_ws( - socket: WebSocket, - ts: LogicalTimeAbsoluteMs, - t: u64, - s: String, - state: Arc>, + socket: WebSocket, ts: LogicalTimeAbsoluteMs, t: u64, s: String, state: Arc>, ) { - let runtime = MaroonTaskRuntime::DelayedMessage(MaroonTaskRuntimeDelayedMessage { - delay: LogicalTimeAbsoluteMs::from_millis(t), - message: s.clone(), - }); - state .schedule( Arc::new(WebSocketWriter::new(socket)), - MaroonTaskStack::new(MaroonTaskState::DelayedMessageTaskBegin), + MaroonTaskStack { + maroon_stack_entries: vec![ + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMs(t)), + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMessage(s.clone())), + MaroonTaskStackEntry::State(MaroonTaskState::DelayedMessageTaskBegin), + ], + }, MaroonTaskHeap::empty(), ts, format!("Delayed by {}ms: `{}`.", t, s), @@ -726,6 +719,7 @@ async fn delay_handler_ws( .await; } +/* async fn divisors_handler( ws: WebSocketUpgrade, Path(a): Path, @@ -962,13 +956,6 @@ async fn execute_pending_operations_inner(state: &mut Arc { fsm.active_tasks.remove(&task_id); } - /* - MaroonStepResult::OldNext(new_state) => { - maroon_task.maroon_stack.maroon_stack_entries.push(MaroonTaskStackEntry::State(new_state)); - fsm.active_tasks.insert(task_id, maroon_task); - fsm.pending_operations.push(TimestampedMaroonTask::new(scheduled_timestamp, task_id)); - } - */ MaroonStepResult::Sleep(sleep_ms, new_states_vec) => { for new_state in new_states_vec.into_iter() { maroon_task.maroon_stack.maroon_stack_entries.push(new_state); @@ -1035,7 +1022,7 @@ async fn main() { let app = Router::new() .route("/", get(root_handler)) .route("/add/{a}/{b}", get(add_handler)) - // .route("/delay/{t}/{s}", get(delay_handler)) + .route("/delay/{t}/{s}", get(delay_handler)) // .route("/divisors/{n}", get(divisors_handler)) // .route("/fibonacci/{n}", get(fibonacci_handler)) .route("/factorial/{n}", get(factorial_handler)) From 10c8cb3d858da11fbf08763402e3ffc3c92cf472 Mon Sep 17 00:00:00 2001 From: Dima Korolev Date: Sat, 31 May 2025 16:58:26 -0700 Subject: [PATCH 5/9] More Rusty! --- step11_ws_state_machine/code/src/main.rs | 202 +++++++++++------------ 1 file changed, 98 insertions(+), 104 deletions(-) diff --git a/step11_ws_state_machine/code/src/main.rs b/step11_ws_state_machine/code/src/main.rs index d2c63f4..82e68e0 100644 --- a/step11_ws_state_machine/code/src/main.rs +++ b/step11_ws_state_machine/code/src/main.rs @@ -348,39 +348,36 @@ enum MaroonStepResult { fn global_step(state: MaroonTaskState, vars: Vec) -> MaroonStepResult { match state { MaroonTaskState::DelayedMessageTaskBegin => { - if let Some(MaroonTaskStackEntryValue::DelayInputMessage(msg)) = vars.get(0) { - if let Some(MaroonTaskStackEntryValue::DelayInputMs(delay_ms)) = vars.get(1) { - let delay_ms = *delay_ms; - let msg = msg.clone(); - MaroonStepResult::Sleep( - LogicalTimeDeltaMs::from_millis(delay_ms), - vec![ - MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMs(delay_ms)), - MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMessage(msg)), - MaroonTaskStackEntry::State(MaroonTaskState::DelayedMessageTaskExecute), - ], - ) - } else { - panic!("Unexpected argument 1 type in `DelayedMessageTaskBegin`: `{:?}`.", vars.get(1)); - } - } else { - panic!("Unexpected argument 0 type in `DelayedMessageTaskBegin`: `{:?}`.", vars.get(0)); - } + let (msg, delay_ms) = match (vars.get(0), vars.get(1)) { + ( + Some(MaroonTaskStackEntryValue::DelayInputMessage(msg)), + Some(MaroonTaskStackEntryValue::DelayInputMs(delay_ms)), + ) => (msg.clone(), *delay_ms), + _ => panic!("Unexpected arguments in DelayedMessageTaskBegin: {:?}", vars), + }; + + MaroonStepResult::Sleep( + LogicalTimeDeltaMs::from_millis(delay_ms), + vec![ + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMs(delay_ms)), + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMessage(msg)), + MaroonTaskStackEntry::State(MaroonTaskState::DelayedMessageTaskExecute), + ], + ) } MaroonTaskState::DelayedMessageTaskExecute => { - if let Some(MaroonTaskStackEntryValue::DelayInputMessage(msg)) = vars.get(0) { - if let Some(MaroonTaskStackEntryValue::DelayInputMs(delay_ms)) = vars.get(1) { - let delay_ms = *delay_ms; - MaroonStepResult::Write( - format_delayed_message(LogicalTimeAbsoluteMs::from_millis(delay_ms), msg), - vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)], - ) - } else { - panic!("Unexpected argument 1 type in `DelayedMessageTaskExecute`: `{:?}`.", vars.get(1)); - } - } else { - panic!("Unexpected argument 0 type in `DelayedMessageTaskExecute`: `{:?}`.", vars.get(0)); - } + let (msg, delay_ms) = match (vars.get(0), vars.get(1)) { + ( + Some(MaroonTaskStackEntryValue::DelayInputMessage(msg)), + Some(MaroonTaskStackEntryValue::DelayInputMs(delay_ms)), + ) => (msg.clone(), *delay_ms), + _ => panic!("Unexpected arguments in DelayedMessageTaskExecute: {:?}", vars), + }; + + MaroonStepResult::Write( + format_delayed_message(LogicalTimeAbsoluteMs::from_millis(delay_ms), &msg), + vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)], + ) } /* MaroonTaskState::DivisorsTaskBegin => { @@ -486,91 +483,88 @@ fn global_step(state: MaroonTaskState, vars: Vec) -> } */ MaroonTaskState::FactorialEntry => { - if let Some(MaroonTaskStackEntryValue::FactorialInput(n)) = vars.get(0) { - let n = *n; - MaroonStepResult::Next(vec![ - // This input should be preserved on the stack when `Retrn` takes place. - MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialInput(n)), - // This is the state to `Return` to. - MaroonTaskStackEntry::Retrn(MaroonTaskState::FactorialDone), - // This the argument to the function, which is the state right below this one. - MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialArgument(n)), - // And this is the function to be called, which will ultimately `Return` into `FactorialDone`. - MaroonTaskStackEntry::State(MaroonTaskState::FactorialRecursiveCall), - ]) - } else { - panic!("Unexpected argument 0 type in `FactorialEntry`: `{:?}`.", vars.get(0)); - } + let n = match vars.get(0) { + Some(MaroonTaskStackEntryValue::FactorialInput(n)) => *n, + _ => panic!("Unexpected arguments in FactorialEntry: {:?}", vars), + }; + + MaroonStepResult::Next(vec![ + // This input should be preserved on the stack when `Retrn` takes place. + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialInput(n)), + // This is the state to `Return` to. + MaroonTaskStackEntry::Retrn(MaroonTaskState::FactorialDone), + // This the argument to the function, which is the state right below this one. + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialArgument(n)), + // And this is the function to be called, which will ultimately `Return` into `FactorialDone`. + MaroonTaskStackEntry::State(MaroonTaskState::FactorialRecursiveCall), + ]) } MaroonTaskState::FactorialRecursiveCall => { - if let Some(MaroonTaskStackEntryValue::FactorialArgument(n)) = vars.get(0) { - let n = *n; - MaroonStepResult::Write( - format!("f({n})"), - // TODO(dkorolev): This `vars` argument should be a helper accessor, to prevent these unnecessary `move`-s. - vec![ - MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialArgument(n)), - MaroonTaskStackEntry::State(MaroonTaskState::FactorialRecursionPostWrite), - ], - ) - } else { - panic!("Unexpected argument 0 type in `FactorialRecursiveCall`: `{:?}`.", vars.get(0)); - } + let n = match vars.get(0) { + Some(MaroonTaskStackEntryValue::FactorialArgument(n)) => *n, + _ => panic!("Unexpected arguments in FactorialRecursiveCall: {:?}", vars), + }; + + MaroonStepResult::Write( + format!("f({n})"), + vec![ + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialArgument(n)), + MaroonTaskStackEntry::State(MaroonTaskState::FactorialRecursionPostWrite), + ], + ) } MaroonTaskState::FactorialRecursionPostWrite => { - if let Some(MaroonTaskStackEntryValue::FactorialArgument(n)) = vars.get(0) { - let n = *n; - MaroonStepResult::Sleep( - LogicalTimeDeltaMs::from_millis(n * 50), - vec![ - MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialArgument(n)), - MaroonTaskStackEntry::State(MaroonTaskState::FactorialRecursionPostSleep), - ], - ) - } else { - panic!("Unexpected argument 0 type in `FactorialRecursionPostWrite`: `{:?}`.", vars.get(0)); - } + let n = match vars.get(0) { + Some(MaroonTaskStackEntryValue::FactorialArgument(n)) => *n, + _ => panic!("Unexpected arguments in FactorialRecursionPostWrite: {:?}", vars), + }; + + MaroonStepResult::Sleep( + LogicalTimeDeltaMs::from_millis(n * 50), + vec![ + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialArgument(n)), + MaroonTaskStackEntry::State(MaroonTaskState::FactorialRecursionPostSleep), + ], + ) } MaroonTaskState::FactorialRecursionPostSleep => { - if let Some(MaroonTaskStackEntryValue::FactorialArgument(n)) = vars.get(0) { - let n = *n; - if n > 1 { - MaroonStepResult::Next(vec![ - MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialArgument(n)), - MaroonTaskStackEntry::Retrn(MaroonTaskState::FactorialRecursionPostRecursiveCall), - MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialArgument(n - 1)), - MaroonTaskStackEntry::State(MaroonTaskState::FactorialRecursiveCall), - ]) - } else { - MaroonStepResult::Return(MaroonTaskStackEntryValue::FactorialReturnValue(1)) - } + let n = match vars.get(0) { + Some(MaroonTaskStackEntryValue::FactorialArgument(n)) => *n, + _ => panic!("Unexpected arguments in FactorialRecursionPostSleep: {:?}", vars), + }; + + if n > 1 { + MaroonStepResult::Next(vec![ + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialArgument(n)), + MaroonTaskStackEntry::Retrn(MaroonTaskState::FactorialRecursionPostRecursiveCall), + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::FactorialArgument(n - 1)), + MaroonTaskStackEntry::State(MaroonTaskState::FactorialRecursiveCall), + ]) } else { - panic!("Unexpected argument 0 type in `FactorialRecursionPostSleep`: `{:?}`.", vars.get(0)); + MaroonStepResult::Return(MaroonTaskStackEntryValue::FactorialReturnValue(1)) } } MaroonTaskState::FactorialRecursionPostRecursiveCall => { - if let Some(MaroonTaskStackEntryValue::FactorialArgument(n)) = vars.get(1) { - let n = *n; - if let Some(MaroonTaskStackEntryValue::FactorialReturnValue(a)) = vars.get(0) { - let a = *a; - MaroonStepResult::Return(MaroonTaskStackEntryValue::FactorialReturnValue(a * n)) - } else { - panic!("Unexpected argument 0 type in `FactorialRecursionPostSleep`: `{:?}`.", vars.get(1)); - } - } else { - panic!("Unexpected argument 1 type in `FactorialRecursionPostSleep`: `{:?}`.", vars.get(0)); - } + let (a, n) = match (vars.get(0), vars.get(1)) { + ( + Some(MaroonTaskStackEntryValue::FactorialReturnValue(a)), + Some(MaroonTaskStackEntryValue::FactorialArgument(n)), + ) => (*a, *n), + _ => panic!("Unexpected arguments in FactorialRecursionPostRecursiveCall: {:?}", vars), + }; + + MaroonStepResult::Return(MaroonTaskStackEntryValue::FactorialReturnValue(a * n)) } MaroonTaskState::FactorialDone => { - if let Some(MaroonTaskStackEntryValue::FactorialReturnValue(r)) = vars.get(0) { - if let Some(MaroonTaskStackEntryValue::FactorialInput(n)) = vars.get(1) { - MaroonStepResult::Write(format!("{n}!={r}"), vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)]) - } else { - panic!("Unexpected argument 1 type in `FactorialDone`."); - } - } else { - panic!("Unexpected argument 0 type in `FactorialDone`."); - } + let (r, n) = match (vars.get(0), vars.get(1)) { + ( + Some(MaroonTaskStackEntryValue::FactorialReturnValue(r)), + Some(MaroonTaskStackEntryValue::FactorialInput(n)), + ) => (*r, *n), + _ => panic!("Unexpected arguments in FactorialDone: {:?}", vars), + }; + + MaroonStepResult::Write(format!("{n}!={r}"), vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)]) } MaroonTaskState::Completed => MaroonStepResult::Done, } From e3e2eaa96862e4aa073470a588697742adff1f49 Mon Sep 17 00:00:00 2001 From: Dima Korolev Date: Sat, 31 May 2025 17:10:07 -0700 Subject: [PATCH 6/9] Starting with the Divisors task using a Maroon Heap (not Maroon Runtime). --- step11_ws_state_machine/code/src/main.rs | 25 +++++++++++------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/step11_ws_state_machine/code/src/main.rs b/step11_ws_state_machine/code/src/main.rs index 82e68e0..d819a28 100644 --- a/step11_ws_state_machine/code/src/main.rs +++ b/step11_ws_state_machine/code/src/main.rs @@ -259,22 +259,19 @@ struct MaroonTaskStack { maroon_stack_entries: Vec, } -// NOTE(dkorolev): Empty for now. =) -struct MaroonTaskHeap {} - -impl MaroonTaskHeap { - fn empty() -> Self { - Self {} - } -} - -/* #[derive(Clone, Debug)] -struct MaroonTaskRuntimeDivisors { +struct MaroonTaskHeapDivisors { n: u64, i: u64, } +#[derive(Clone, Debug)] +enum MaroonTaskHeap { + Empty, + Divisors(MaroonTaskHeapDivisors), +} + +/* #[derive(Clone, Debug)] struct MaroonTaskRuntimeFibonacci { n: u64, @@ -706,7 +703,7 @@ async fn delay_handler_ws( MaroonTaskStackEntry::State(MaroonTaskState::DelayedMessageTaskBegin), ], }, - MaroonTaskHeap::empty(), + MaroonTaskHeap::Empty, ts, format!("Delayed by {}ms: `{}`.", t, s), ) @@ -792,7 +789,7 @@ async fn factorial_handler_ws( MaroonTaskStackEntry::State(MaroonTaskState::FactorialEntry), ], }, - MaroonTaskHeap::empty(), + MaroonTaskHeap::Empty, ts, format!("Factorial of {n}"), ) @@ -1309,7 +1306,7 @@ mod tests { MaroonTaskStackEntry::State(MaroonTaskState::FactorialEntry), ], }, - MaroonTaskHeap::empty(), + MaroonTaskHeap::Empty, LogicalTimeAbsoluteMs::from_millis(0), "Factorial of 5".to_string(), ) From 94ee848fb1581f72510cb6bfbd06a939d653a0a3 Mon Sep 17 00:00:00 2001 From: Dima Korolev Date: Sat, 31 May 2025 17:16:34 -0700 Subject: [PATCH 7/9] Surprisingly, this compiled quickly. --- step11_ws_state_machine/code/src/main.rs | 28 +++++++++++++----------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/step11_ws_state_machine/code/src/main.rs b/step11_ws_state_machine/code/src/main.rs index d819a28..41c5a45 100644 --- a/step11_ws_state_machine/code/src/main.rs +++ b/step11_ws_state_machine/code/src/main.rs @@ -187,14 +187,14 @@ impl Writer for WebSocketWriter { enum MaroonTaskState { Completed, /* - DivisorsTaskBegin, - DivisorsTaskIteration, - DivisorsPrintAndMoveOn, FibonacciTaskBegin, FibonacciTaskCalculate, FibonacciTaskResult, FibonacciTaskStep, */ + DivisorsTaskBegin, + DivisorsTaskIteration, + DivisorsPrintAndMoveOn, DelayedMessageTaskBegin, DelayedMessageTaskExecute, FactorialEntry, @@ -342,7 +342,9 @@ enum MaroonStepResult { Return(MaroonTaskStackEntryValue), } -fn global_step(state: MaroonTaskState, vars: Vec) -> MaroonStepResult { +fn global_step( + state: MaroonTaskState, vars: Vec, heap: &mut MaroonTaskHeap, +) -> MaroonStepResult { match state { MaroonTaskState::DelayedMessageTaskBegin => { let (msg, delay_ms) = match (vars.get(0), vars.get(1)) { @@ -376,17 +378,16 @@ fn global_step(state: MaroonTaskState, vars: Vec) -> vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)], ) } - /* MaroonTaskState::DivisorsTaskBegin => { - if let MaroonTaskRuntime::Divisors(data) = runtime { + if let MaroonTaskHeap::Divisors(data) = heap { data.i = data.n; - MaroonStepResult::OldNext(MaroonTaskState::DivisorsTaskIteration) + MaroonStepResult::Next(vec![MaroonTaskStackEntry::State(MaroonTaskState::DivisorsTaskIteration)]) } else { - panic!("Runtime type mismatch for `DivisorsTaskBegin`."); + panic!("Heap type mismatch for `DivisorsTaskBegin`."); } } MaroonTaskState::DivisorsTaskIteration => { - if let MaroonTaskRuntime::Divisors(data) = runtime { + if let MaroonTaskHeap::Divisors(data) = heap { let mut i = data.i; while i > 0 && data.n % i != 0 { i -= 1; @@ -404,11 +405,11 @@ fn global_step(state: MaroonTaskState, vars: Vec) -> ) } } else { - panic!("Runtime type mismatch for `DivisorsTaskIteration`."); + panic!("Heap type mismatch for `DivisorsTaskIteration`."); } } MaroonTaskState::DivisorsPrintAndMoveOn => { - if let MaroonTaskRuntime::Divisors(data) = runtime { + if let MaroonTaskHeap::Divisors(data) = heap { let result = MaroonStepResult::Write( format_divisor_found(data.n, data.i), vec![MaroonTaskStackEntry::State(MaroonTaskState::DivisorsTaskIteration)], @@ -416,9 +417,10 @@ fn global_step(state: MaroonTaskState, vars: Vec) -> data.i -= 1; result } else { - panic!("Runtime type mismatch for `DivisorsPrintAndMoveOn`."); + panic!("Heap type mismatch for `DivisorsPrintAndMoveOn`."); } } + /* MaroonTaskState::FibonacciTaskBegin => { if let MaroonTaskRuntime::Fibonacci(data) = runtime { if data.n <= 1 { @@ -939,7 +941,7 @@ async fn execute_pending_operations_inner(state: &mut Arc Date: Sat, 31 May 2025 17:23:13 -0700 Subject: [PATCH 8/9] Uncommented and ported the remaining logic and tests. --- step11_ws_state_machine/code/src/main.rs | 206 +++++++++++++---------- 1 file changed, 118 insertions(+), 88 deletions(-) diff --git a/step11_ws_state_machine/code/src/main.rs b/step11_ws_state_machine/code/src/main.rs index 41c5a45..4f84c86 100644 --- a/step11_ws_state_machine/code/src/main.rs +++ b/step11_ws_state_machine/code/src/main.rs @@ -186,17 +186,15 @@ impl Writer for WebSocketWriter { #[derive(Clone, Debug)] enum MaroonTaskState { Completed, - /* + DelayedMessageTaskBegin, + DelayedMessageTaskExecute, + DivisorsTaskBegin, + DivisorsTaskIteration, + DivisorsPrintAndMoveOn, FibonacciTaskBegin, FibonacciTaskCalculate, FibonacciTaskResult, FibonacciTaskStep, - */ - DivisorsTaskBegin, - DivisorsTaskIteration, - DivisorsPrintAndMoveOn, - DelayedMessageTaskBegin, - DelayedMessageTaskExecute, FactorialEntry, FactorialRecursiveCall, FactorialRecursionPostWrite, @@ -266,21 +264,20 @@ struct MaroonTaskHeapDivisors { } #[derive(Clone, Debug)] -enum MaroonTaskHeap { - Empty, - Divisors(MaroonTaskHeapDivisors), -} - -/* -#[derive(Clone, Debug)] -struct MaroonTaskRuntimeFibonacci { +struct MaroonTaskHeapFibonacci { n: u64, index: u64, a: u64, b: u64, delay_ms: LogicalTimeDeltaMs, } -*/ + +#[derive(Clone, Debug)] +enum MaroonTaskHeap { + Empty, + Divisors(MaroonTaskHeapDivisors), + Fibonacci(MaroonTaskHeapFibonacci), +} #[cfg(not(test))] fn format_delayed_message(sleep_ms: LogicalTimeAbsoluteMs, message: &str) -> String { @@ -420,9 +417,59 @@ fn global_step( panic!("Heap type mismatch for `DivisorsPrintAndMoveOn`."); } } - /* MaroonTaskState::FibonacciTaskBegin => { - if let MaroonTaskRuntime::Fibonacci(data) = runtime { + if let MaroonTaskHeap::Fibonacci(data) = heap { + if data.n <= 1 { + MaroonStepResult::Write( + format_fibonacci_result(data.n, data.n), + vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)], + ) + } else { + data.index = 1; + data.a = 0; + data.b = 1; + MaroonStepResult::Next(vec![MaroonTaskStackEntry::State(MaroonTaskState::FibonacciTaskCalculate)]) + } + } else { + panic!("Heap type mismatch for `DivisorsTaskBegin`."); + } + } + MaroonTaskState::DivisorsTaskIteration => { + if let MaroonTaskHeap::Divisors(data) = heap { + let mut i = data.i; + while i > 0 && data.n % i != 0 { + i -= 1; + } + if i == 0 { + MaroonStepResult::Write( + format_divisors_done(data.n), + vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)], + ) + } else { + data.i = i; + MaroonStepResult::Sleep( + LogicalTimeDeltaMs::from_millis(i * 10), + vec![MaroonTaskStackEntry::State(MaroonTaskState::DivisorsPrintAndMoveOn)], + ) + } + } else { + panic!("Heap type mismatch for `DivisorsTaskIteration`."); + } + } + MaroonTaskState::DivisorsPrintAndMoveOn => { + if let MaroonTaskHeap::Divisors(data) = heap { + let result = MaroonStepResult::Write( + format_divisor_found(data.n, data.i), + vec![MaroonTaskStackEntry::State(MaroonTaskState::DivisorsTaskIteration)], + ); + data.i -= 1; + result + } else { + panic!("Heap type mismatch for `DivisorsPrintAndMoveOn`."); + } + } + MaroonTaskState::FibonacciTaskBegin => { + if let MaroonTaskHeap::Fibonacci(data) = heap { if data.n <= 1 { MaroonStepResult::Write( format_fibonacci_result(data.n, data.n), @@ -432,16 +479,16 @@ fn global_step( data.index = 1; data.a = 0; data.b = 1; - MaroonStepResult::OldNext(MaroonTaskState::FibonacciTaskCalculate) + MaroonStepResult::Next(vec![MaroonTaskStackEntry::State(MaroonTaskState::FibonacciTaskBegin)]) } } else { - panic!("Runtime type mismatch for `FibonacciTaskBegin`."); + panic!("Heap type mismatch for `FibonacciTaskBegin`."); } } MaroonTaskState::FibonacciTaskCalculate => { - if let MaroonTaskRuntime::Fibonacci(data) = runtime { + if let MaroonTaskHeap::Fibonacci(data) = heap { if data.index >= data.n { - MaroonStepResult::OldNext(MaroonTaskState::FibonacciTaskResult) + MaroonStepResult::Next(vec![MaroonTaskStackEntry::State(MaroonTaskState::FibonacciTaskResult)]) } else { let delay = 5 * data.index; data.delay_ms = LogicalTimeDeltaMs::from_millis(delay); @@ -451,11 +498,11 @@ fn global_step( ) } } else { - panic!("Runtime type mismatch for `FibonacciTaskCalculate`."); + panic!("Heap type mismatch for `FibonacciTaskCalculate`."); } } MaroonTaskState::FibonacciTaskStep => { - if let MaroonTaskRuntime::Fibonacci(data) = runtime { + if let MaroonTaskHeap::Fibonacci(data) = heap { let next_index = data.index + 1; let next_a = data.b; let next_b = data.a + data.b; @@ -467,20 +514,19 @@ fn global_step( vec![MaroonTaskStackEntry::State(MaroonTaskState::FibonacciTaskCalculate)], ) } else { - panic!("Runtime type mismatch for `FibonacciTaskStep`."); + panic!("Heap type mismatch for `FibonacciTaskStep`."); } } MaroonTaskState::FibonacciTaskResult => { - if let MaroonTaskRuntime::Fibonacci(data) = runtime { + if let MaroonTaskHeap::Fibonacci(data) = heap { MaroonStepResult::Write( format_fibonacci_result(data.n, data.b), vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)], ) } else { - panic!("Runtime type mismatch for `FibonacciTaskResult`."); + panic!("Heap type mismatch for `FibonacciTaskResult`."); } } - */ MaroonTaskState::FactorialEntry => { let n = match vars.get(0) { Some(MaroonTaskStackEntryValue::FactorialInput(n)) => *n, @@ -712,28 +758,20 @@ async fn delay_handler_ws( .await; } -/* async fn divisors_handler( - ws: WebSocketUpgrade, - Path(a): Path, - State(state): State>>, + ws: WebSocketUpgrade, Path(a): Path, State(state): State>>, ) -> impl IntoResponse { ws.on_upgrade(move |socket| divisors_handler_ws(socket, state.timer.millis_since_start(), a, state)) } async fn divisors_handler_ws( - socket: WebSocket, - ts: LogicalTimeAbsoluteMs, - n: u64, - state: Arc>, + socket: WebSocket, ts: LogicalTimeAbsoluteMs, n: u64, state: Arc>, ) { - let runtime = MaroonTaskRuntime::Divisors(MaroonTaskRuntimeDivisors { n, i: n }); - state .schedule( Arc::new(WebSocketWriter::new(socket)), - MaroonTaskStack::new(MaroonTaskState::DivisorsTaskBegin), - MaroonTaskHeap::empty(), + MaroonTaskStack { maroon_stack_entries: vec![MaroonTaskStackEntry::State(MaroonTaskState::DivisorsTaskBegin)] }, + MaroonTaskHeap::Divisors(MaroonTaskHeapDivisors { n, i: n }), ts, format!("Divisors of {}", n), ) @@ -741,37 +779,30 @@ async fn divisors_handler_ws( } async fn fibonacci_handler( - ws: WebSocketUpgrade, - Path(n): Path, - State(state): State>>, + ws: WebSocketUpgrade, Path(n): Path, State(state): State>>, ) -> impl IntoResponse { ws.on_upgrade(move |socket| fibonacci_handler_ws(socket, state.timer.millis_since_start(), n, state)) } async fn fibonacci_handler_ws( - socket: WebSocket, - ts: LogicalTimeAbsoluteMs, - n: u64, - state: Arc>, + socket: WebSocket, ts: LogicalTimeAbsoluteMs, n: u64, state: Arc>, ) { - let runtime = MaroonTaskRuntime::Fibonacci(MaroonTaskRuntimeFibonacci { - n, - index: 0, - a: 0, - b: 0, - delay_ms: LogicalTimeDeltaMs::from_millis(0), - }); state .schedule( Arc::new(WebSocketWriter::new(socket)), - MaroonTaskStack::new(MaroonTaskState::FibonacciTaskBegin), - MaroonTaskHeap::empty(), + MaroonTaskStack { maroon_stack_entries: vec![MaroonTaskStackEntry::State(MaroonTaskState::FibonacciTaskBegin)] }, + MaroonTaskHeap::Fibonacci(MaroonTaskHeapFibonacci { + n, + index: 0, + a: 0, + b: 0, + delay_ms: LogicalTimeDeltaMs::from_millis(0), + }), ts, format!("Fibonacci number {n}"), ) .await; } -*/ async fn factorial_handler( ws: WebSocketUpgrade, Path(n): Path, State(state): State>>, @@ -1016,8 +1047,8 @@ async fn main() { .route("/", get(root_handler)) .route("/add/{a}/{b}", get(add_handler)) .route("/delay/{t}/{s}", get(delay_handler)) - // .route("/divisors/{n}", get(divisors_handler)) - // .route("/fibonacci/{n}", get(fibonacci_handler)) + .route("/divisors/{n}", get(divisors_handler)) + .route("/fibonacci/{n}", get(fibonacci_handler)) .route("/factorial/{n}", get(factorial_handler)) .route("/ack/{m}/{n}", get(ackermann_handler)) // Do try `/ack/3/4`, but not `/ack/4/*`, hehe. .route("/state", get(state_handler)) @@ -1106,7 +1137,6 @@ mod tests { } } - /* #[tokio::test] async fn test_state_machine_and_execution() { let timer = Arc::new(MockTimer::new(0)); @@ -1125,9 +1155,8 @@ mod tests { app_state .schedule( Arc::clone(&writer), - MaroonTaskStack::new(MaroonTaskState::DivisorsTaskBegin), - MaroonTaskHeap::empty(), - MaroonTaskRuntime::Divisors(MaroonTaskRuntimeDivisors { n: 12, i: 12 }), + MaroonTaskStack { maroon_stack_entries: vec![MaroonTaskStackEntry::State(MaroonTaskState::DivisorsTaskBegin)] }, + MaroonTaskHeap::Divisors(MaroonTaskHeapDivisors { n: 12, i: 12 }), LogicalTimeAbsoluteMs::from_millis(0), "Divisors of 12".to_string(), ) @@ -1135,12 +1164,14 @@ mod tests { app_state .schedule( Arc::clone(&writer), - MaroonTaskStack::new(MaroonTaskState::DelayedMessageTaskBegin), - MaroonTaskHeap::empty(), - MaroonTaskRuntime::DelayedMessage(MaroonTaskRuntimeDelayedMessage { - delay: LogicalTimeAbsoluteMs::from_millis(225), - message: "HI".to_string(), - }), + MaroonTaskStack { + maroon_stack_entries: vec![ + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMs(225)), + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMessage("HI".to_string())), + MaroonTaskStackEntry::State(MaroonTaskState::DelayedMessageTaskBegin), + ], + }, + MaroonTaskHeap::Empty, LogicalTimeAbsoluteMs::from_millis(0), "Hello".to_string(), ) @@ -1148,12 +1179,14 @@ mod tests { app_state .schedule( Arc::clone(&writer), - MaroonTaskStack::new(MaroonTaskState::DelayedMessageTaskBegin), - MaroonTaskHeap::empty(), - MaroonTaskRuntime::DelayedMessage(MaroonTaskRuntimeDelayedMessage { - delay: LogicalTimeAbsoluteMs::from_millis(75), - message: "BYE".to_string(), - }), + MaroonTaskStack { + maroon_stack_entries: vec![ + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMs(75)), + MaroonTaskStackEntry::Value(MaroonTaskStackEntryValue::DelayInputMessage("BYE".to_string())), + MaroonTaskStackEntry::State(MaroonTaskState::DelayedMessageTaskBegin), + ], + }, + MaroonTaskHeap::Empty, LogicalTimeAbsoluteMs::from_millis(200), "Bye".to_string(), ) @@ -1186,9 +1219,8 @@ mod tests { app_state .schedule( Arc::clone(&writer), - MaroonTaskStack::new(MaroonTaskState::DivisorsTaskBegin), - MaroonTaskHeap::empty(), - MaroonTaskRuntime::Divisors(MaroonTaskRuntimeDivisors { n: 8, i: 8 }), + MaroonTaskStack { maroon_stack_entries: vec![MaroonTaskStackEntry::State(MaroonTaskState::DivisorsTaskBegin)] }, + MaroonTaskHeap::Divisors(MaroonTaskHeapDivisors { n: 8, i: 8 }), LogicalTimeAbsoluteMs::from_millis(10_000), "".to_string(), ) @@ -1196,9 +1228,8 @@ mod tests { app_state .schedule( Arc::clone(&writer), - MaroonTaskStack::new(MaroonTaskState::DivisorsTaskBegin), - MaroonTaskHeap::empty(), - MaroonTaskRuntime::Divisors(MaroonTaskRuntimeDivisors { n: 9, i: 9 }), + MaroonTaskStack { maroon_stack_entries: vec![MaroonTaskStackEntry::State(MaroonTaskState::DivisorsTaskBegin)] }, + MaroonTaskHeap::Divisors(MaroonTaskHeapDivisors { n: 9, i: 9 }), LogicalTimeAbsoluteMs::from_millis(10_001), "".to_string(), ) @@ -1206,9 +1237,8 @@ mod tests { app_state .schedule( Arc::clone(&writer), - MaroonTaskStack::new(MaroonTaskState::DivisorsTaskBegin), - MaroonTaskHeap::empty(), - MaroonTaskRuntime::Divisors(MaroonTaskRuntimeDivisors { n: 3, i: 3 }), + MaroonTaskStack { maroon_stack_entries: vec![MaroonTaskStackEntry::State(MaroonTaskState::DivisorsTaskBegin)] }, + MaroonTaskHeap::Divisors(MaroonTaskHeapDivisors { n: 3, i: 3 }), LogicalTimeAbsoluteMs::from_millis(10_002), "".to_string(), ) @@ -1252,9 +1282,10 @@ mod tests { app_state .schedule( Arc::clone(&writer), - MaroonTaskStack::new(MaroonTaskState::FibonacciTaskBegin), - MaroonTaskHeap::empty(), - MaroonTaskRuntime::Fibonacci(MaroonTaskRuntimeFibonacci { + MaroonTaskStack { + maroon_stack_entries: vec![MaroonTaskStackEntry::State(MaroonTaskState::FibonacciTaskBegin)], + }, + MaroonTaskHeap::Fibonacci(MaroonTaskHeapFibonacci { n: 5, index: 0, a: 0, @@ -1282,7 +1313,6 @@ mod tests { assert_eq!(expected, writer.get_outputs_as_string()); } - */ #[tokio::test] async fn test_factorial_task() { From b8fedc185950b9c791b91769530710b750481fb7 Mon Sep 17 00:00:00 2001 From: Dima Korolev Date: Sat, 31 May 2025 17:35:50 -0700 Subject: [PATCH 9/9] Removed redundant code and fixed the warnings. --- step11_ws_state_machine/code/src/main.rs | 55 ++---------------------- 1 file changed, 3 insertions(+), 52 deletions(-) diff --git a/step11_ws_state_machine/code/src/main.rs b/step11_ws_state_machine/code/src/main.rs index 4f84c86..649ad10 100644 --- a/step11_ws_state_machine/code/src/main.rs +++ b/step11_ws_state_machine/code/src/main.rs @@ -32,6 +32,7 @@ impl LogicalTimeAbsoluteMs { Self(millis) } + #[cfg(test)] pub fn as_millis(&self) -> u64 { self.0 } @@ -230,6 +231,7 @@ const fn maroon_task_state_local_vars_count(e: &MaroonTaskState) -> usize { } // For a given `S`, if the maroon stack contains `Retrn(S)`, how many entries above it are its local stack vars. +#[cfg(test)] const fn maroon_task_state_return_local_vars_count(e: &MaroonTaskState) -> usize { match e { MaroonTaskState::FactorialDone => 1, // [FactorialInput] @@ -434,57 +436,6 @@ fn global_step( panic!("Heap type mismatch for `DivisorsTaskBegin`."); } } - MaroonTaskState::DivisorsTaskIteration => { - if let MaroonTaskHeap::Divisors(data) = heap { - let mut i = data.i; - while i > 0 && data.n % i != 0 { - i -= 1; - } - if i == 0 { - MaroonStepResult::Write( - format_divisors_done(data.n), - vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)], - ) - } else { - data.i = i; - MaroonStepResult::Sleep( - LogicalTimeDeltaMs::from_millis(i * 10), - vec![MaroonTaskStackEntry::State(MaroonTaskState::DivisorsPrintAndMoveOn)], - ) - } - } else { - panic!("Heap type mismatch for `DivisorsTaskIteration`."); - } - } - MaroonTaskState::DivisorsPrintAndMoveOn => { - if let MaroonTaskHeap::Divisors(data) = heap { - let result = MaroonStepResult::Write( - format_divisor_found(data.n, data.i), - vec![MaroonTaskStackEntry::State(MaroonTaskState::DivisorsTaskIteration)], - ); - data.i -= 1; - result - } else { - panic!("Heap type mismatch for `DivisorsPrintAndMoveOn`."); - } - } - MaroonTaskState::FibonacciTaskBegin => { - if let MaroonTaskHeap::Fibonacci(data) = heap { - if data.n <= 1 { - MaroonStepResult::Write( - format_fibonacci_result(data.n, data.n), - vec![MaroonTaskStackEntry::State(MaroonTaskState::Completed)], - ) - } else { - data.index = 1; - data.a = 0; - data.b = 1; - MaroonStepResult::Next(vec![MaroonTaskStackEntry::State(MaroonTaskState::FibonacciTaskBegin)]) - } - } else { - panic!("Heap type mismatch for `FibonacciTaskBegin`."); - } - } MaroonTaskState::FibonacciTaskCalculate => { if let MaroonTaskHeap::Fibonacci(data) = heap { if data.index >= data.n { @@ -890,7 +841,7 @@ fn debug_validate_maroon_stack(stk: &Vec) { } for _ in 0..n { i = i - 1; - if let MaroonTaskStackEntry::Value(value) = &stk[i] { + if let MaroonTaskStackEntry::Value(_) = &stk[i] { // OK } else { panic!("In `debug_validate_maroon_stack` expecting value, for non-value, pls examine `{:?}`.", stk);