diff --git a/src/protocol/eval/executor.rs b/src/protocol/eval/executor.rs index 78ab516f15000eec257786982eaa2250d7c3cb02..ac845a93c1640ab5270a557c106b806c13b5618b 100644 --- a/src/protocol/eval/executor.rs +++ b/src/protocol/eval/executor.rs @@ -38,35 +38,34 @@ impl Frame { /// Creates a new execution frame. Does not modify the stack in any way. pub fn new(heap: &Heap, definition_id: DefinitionId, monomorph_idx: i32) -> Self { let definition = &heap[definition_id]; - let first_statement = match definition { - Definition::Component(definition) => definition.body, - Definition::Function(definition) => definition.body, + let (outer_scope_id, first_statement_id) = match definition { + Definition::Component(definition) => (definition.scope, definition.body), + Definition::Function(definition) => (definition.scope, definition.body), _ => unreachable!("initializing frame with {:?} instead of a function/component", definition), }; // Another not-so-pretty thing that has to be replaced somewhere in the // future... - fn determine_max_stack_size(heap: &Heap, block_id: BlockStatementId, max_size: &mut u32) { - let block_stmt = &heap[block_id]; - debug_assert!(block_stmt.next_unique_id_in_scope >= 0); + fn determine_max_stack_size(heap: &Heap, scope_id: ScopeId, max_size: &mut u32) { + let scope = &heap[scope_id]; // Check current block - let cur_size = block_stmt.next_unique_id_in_scope as u32; + let cur_size = scope.next_unique_id_in_scope as u32; if cur_size > *max_size { *max_size = cur_size; } // And child blocks - for child_scope in &block_stmt.scope_node.nested { - determine_max_stack_size(heap, child_scope.to_block(), max_size); + for child_scope in &scope.nested { + determine_max_stack_size(heap, *child_scope, max_size); } } let mut max_stack_size = 0; - determine_max_stack_size(heap, first_statement, &mut max_stack_size); + determine_max_stack_size(heap, outer_scope_id, &mut max_stack_size); Frame{ definition: definition_id, monomorph_idx, - position: first_statement.upcast(), + position: first_statement_id.upcast(), expr_stack: VecDeque::with_capacity(128), expr_values: VecDeque::with_capacity(128), max_stack_size, @@ -826,7 +825,8 @@ impl Prompt { }, Statement::EndBlock(stmt) => { let block = &heap[stmt.start_block]; - self.store.clear_stack(block.first_unique_id_in_scope as usize); + let scope = &heap[block.scope]; + self.store.clear_stack(scope.first_unique_id_in_scope as usize); cur_frame.position = stmt.next; Ok(EvalContinuation::Stepping) @@ -873,9 +873,9 @@ impl Prompt { let test_value = cur_frame.expr_values.pop_back().unwrap(); let test_value = self.store.maybe_read_ref(&test_value).as_bool(); if test_value { - cur_frame.position = stmt.true_body.upcast(); - } else if let Some(false_body) = stmt.false_body { - cur_frame.position = false_body.upcast(); + cur_frame.position = stmt.true_case.body; + } else if let Some(false_body) = stmt.false_case { + cur_frame.position = false_body.body; } else { // Not true, and no false body cur_frame.position = stmt.end_if.upcast(); @@ -885,6 +885,13 @@ impl Prompt { }, Statement::EndIf(stmt) => { cur_frame.position = stmt.next; + let if_stmt = &heap[stmt.start_if]; + debug_assert_eq!( + heap[if_stmt.true_case.scope].first_unique_id_in_scope, + heap[if_stmt.false_case.unwrap_or(if_stmt.true_case).scope].first_unique_id_in_scope, + ); + let scope = &heap[if_stmt.true_case.scope]; + self.store.clear_stack(scope.first_unique_id_in_scope as usize); Ok(EvalContinuation::Stepping) }, Statement::While(stmt) => { @@ -892,7 +899,7 @@ impl Prompt { let test_value = cur_frame.expr_values.pop_back().unwrap(); let test_value = self.store.maybe_read_ref(&test_value).as_bool(); if test_value { - cur_frame.position = stmt.body.upcast(); + cur_frame.position = stmt.body; } else { cur_frame.position = stmt.end_while.upcast(); } @@ -901,7 +908,9 @@ impl Prompt { }, Statement::EndWhile(stmt) => { cur_frame.position = stmt.next; - + let start_while = &heap[stmt.start_while]; + let scope = &heap[start_while.scope]; + self.store.clear_stack(scope.first_unique_id_in_scope as usize); Ok(EvalContinuation::Stepping) }, Statement::Break(stmt) => { @@ -915,27 +924,30 @@ impl Prompt { Ok(EvalContinuation::Stepping) }, Statement::Synchronous(stmt) => { - cur_frame.position = stmt.body.upcast(); + cur_frame.position = stmt.body; Ok(EvalContinuation::SyncBlockStart) }, Statement::EndSynchronous(stmt) => { cur_frame.position = stmt.next; + let start_synchronous = &heap[stmt.start_sync]; + let scope = &heap[start_synchronous.scope]; + self.store.clear_stack(scope.first_unique_id_in_scope as usize); Ok(EvalContinuation::SyncBlockEnd) }, Statement::Fork(stmt) => { if stmt.right_body.is_none() { // No reason to fork - cur_frame.position = stmt.left_body.upcast(); + cur_frame.position = stmt.left_body; } else { // Need to fork if let Some(go_left) = ctx.performed_fork() { // Runtime has created a fork if go_left { - cur_frame.position = stmt.left_body.upcast(); + cur_frame.position = stmt.left_body; } else { - cur_frame.position = stmt.right_body.unwrap().upcast(); + cur_frame.position = stmt.right_body.unwrap(); } } else { // Request the runtime to create a fork of the current @@ -956,6 +968,11 @@ impl Prompt { }, Statement::EndSelect(stmt) => { cur_frame.position = stmt.next; + let start_select = &heap[stmt.start_select]; + if let Some(select_case) = start_select.cases.first() { + let scope = &heap[select_case.scope]; + self.store.clear_stack(scope.first_unique_id_in_scope as usize); + } Ok(EvalContinuation::Stepping) },