diff --git a/src/protocol/parser/pass_stack_size.rs b/src/protocol/parser/pass_stack_size.rs index 1d1dce19b00791ebf8c290caf5287088ab7f1870..60e5ba5a2369557292c59b2c16935e9ee80cc315 100644 --- a/src/protocol/parser/pass_stack_size.rs +++ b/src/protocol/parser/pass_stack_size.rs @@ -9,17 +9,23 @@ use super::visitor::*; // variables will have a unique position "on the stack". pub(crate) struct PassStackSize { definition_buffer: ScopedBuffer, + variable_buffer: ScopedBuffer, + scope_buffer: ScopedBuffer, } impl PassStackSize { pub(crate) fn new() -> Self { return Self{ definition_buffer: ScopedBuffer::with_capacity(BUFFER_INIT_CAP_LARGE), + variable_buffer: ScopedBuffer::with_capacity(BUFFER_INIT_CAP_SMALL), + scope_buffer: ScopedBuffer::with_capacity(BUFFER_INIT_CAP_SMALL), } } } impl Visitor for PassStackSize { + // Top level visitors + fn visit_module(&mut self, ctx: &mut Ctx) -> VisitorResult { let module = ctx.module(); debug_assert_eq!(module.phase, ModuleCompilationPhase::Rewritten); @@ -36,4 +42,79 @@ impl Visitor for PassStackSize { // ctx.module_mut().phase = ModuleCompilationPhase::StackSizeStuffAndStuff; return Ok(()) } + + fn visit_function_definition(&mut self, ctx: &mut Ctx, id: FunctionDefinitionId) -> VisitorResult { + let definition = &ctx.heap[id]; + let scope_id = definition.scope; + + self.visit_scope_and_assign_local_ids(ctx, scope_id, 0); + return Ok(()) + } + + fn visit_component_definition(&mut self, ctx: &mut Ctx, id: ComponentDefinitionId) -> VisitorResult { + let definition = &ctx.heap[id]; + let scope_id = definition.scope; + + self.visit_scope_and_assign_local_ids(ctx, scope_id, 0); + return Ok(()) + } +} + +impl PassStackSize { + fn visit_scope_and_assign_local_ids(&mut self, ctx: &mut Ctx, scope_id: ScopeId, mut variable_counter: i32) { + let scope = &mut ctx.heap[scope_id]; + scope.first_unique_id_in_scope = variable_counter; + + let variable_section = self.variable_buffer.start_section_initialized(&scope.variables); + let child_scope_section = self.scope_buffer.start_section_initialized(&scope.nested); + + let mut variable_index = 0; + let mut child_scope_index = 0; + + loop { + // Determine relative positions of variable and scope to determine + // which one occurs first within the current scope. + let variable_relative_pos; + if variable_index < variable_section.len() { + let variable_id = variable_section[variable_index]; + let variable = &ctx.heap[variable_id]; + variable_relative_pos = variable.relative_pos_in_parent; + } else { + variable_relative_pos = i32::MAX; + } + + let child_scope_relative_pos; + if child_scope_index < child_scope_section.len() { + let child_scope_id = child_scope_section[child_scope_index]; + let child_scope = &ctx.heap[child_scope_id]; + child_scope_relative_pos = child_scope.relative_pos_in_parent; + } else { + child_scope_relative_pos = i32::MAX; + } + + if variable_relative_pos == i32::MAX && child_scope_relative_pos == i32::MAX { + // Done, no more elements in the scope to consider + break; + } + + // Label the variable/scope, whichever comes first. + if variable_relative_pos <= child_scope_relative_pos { + debug_assert_ne!(variable_relative_pos, child_scope_relative_pos, "checking if this ever happens"); + let variable = &mut ctx.heap[variable_section[variable_index]]; + variable.unique_id_in_scope = variable_counter; + variable_counter += 1; + variable_index += 1; + } else { + let child_scope_id = child_scope_section[child_scope_index]; + self.visit_scope_and_assign_local_ids(ctx, child_scope_id, variable_counter); + child_scope_index += 1; + } + } + + variable_section.forget(); + child_scope_section.forget(); + + let scope = &mut ctx.heap[scope_id]; + scope.next_unique_id_in_scope = variable_counter; + } } \ No newline at end of file diff --git a/src/protocol/parser/pass_validation_linking.rs b/src/protocol/parser/pass_validation_linking.rs index a57cf0ff19b0ee10308c3779fcec36044d40cfe9..e7e2345d34b94f8b63535a1f5a9b1ca7c892c9a9 100644 --- a/src/protocol/parser/pass_validation_linking.rs +++ b/src/protocol/parser/pass_validation_linking.rs @@ -238,10 +238,8 @@ impl Visitor for PassValidationLinking { // Assign total number of expressions and assign an in-block unique ID // to each of the locals in the procedure. let definition = &mut ctx.heap[id]; - let definition_scope = definition.scope; definition.num_expressions_in_body = self.next_expr_index; - self.visit_scope_and_assign_local_ids(ctx, definition_scope, 0); self.resolve_pending_control_flow_targets(ctx)?; Ok(()) @@ -275,9 +273,8 @@ impl Visitor for PassValidationLinking { // Assign total number of expressions and assign an in-block unique ID // to each of the locals in the procedure. let definition = &mut ctx.heap[id]; - let definition_scope = definition.scope; definition.num_expressions_in_body = self.next_expr_index; - self.visit_scope_and_assign_local_ids(ctx, definition_scope, 0); + self.resolve_pending_control_flow_targets(ctx)?; Ok(()) @@ -1500,68 +1497,6 @@ impl PassValidationLinking { self.relative_pos_in_parent = scope_to_restore.1; } - fn visit_scope_and_assign_local_ids(&mut self, ctx: &mut Ctx, scope_id: ScopeId, mut variable_counter: i32) { - let scope = &mut ctx.heap[scope_id]; - scope.first_unique_id_in_scope = variable_counter; - - let variable_section = self.variable_buffer.start_section_initialized(&scope.variables); - let child_scope_section = self.scope_buffer.start_section_initialized(&scope.nested); - - let mut variable_index = 0; - let mut child_scope_index = 0; - - loop { - // Determine relative positions of variable and scope to determine - // which one occurs first within the current scope. - let variable_relative_pos; - if variable_index < variable_section.len() { - let variable_id = variable_section[variable_index]; - let variable = &ctx.heap[variable_id]; - variable_relative_pos = variable.relative_pos_in_parent; - } else { - variable_relative_pos = i32::MAX; - } - - let child_scope_relative_pos; - if child_scope_index < child_scope_section.len() { - let child_scope_id = child_scope_section[child_scope_index]; - let child_scope = &ctx.heap[child_scope_id]; - child_scope_relative_pos = child_scope.relative_pos_in_parent; - } else { - child_scope_relative_pos = i32::MAX; - } - - if variable_relative_pos == i32::MAX && child_scope_relative_pos == i32::MAX { - // Done, no more elements in the scope to consider - break; - } - - // Label the variable/scope, whichever comes first. When dealing - // with binding variables, where both variable and scope are - // considered to have the same position in the scope, we treat the - // variable first. - // TODO: Think about this some more, isn't it correct that we - // consider it part of the fresh scope? So we'll have to deal with - // the scope first, and add the variable to that scope? - if variable_relative_pos <= child_scope_relative_pos { - let variable = &mut ctx.heap[variable_section[variable_index]]; - variable.unique_id_in_scope = variable_counter; - variable_counter += 1; - variable_index += 1; - } else { - let child_scope_id = child_scope_section[child_scope_index]; - self.visit_scope_and_assign_local_ids(ctx, child_scope_id, variable_counter); - child_scope_index += 1; - } - } - - variable_section.forget(); - child_scope_section.forget(); - - let scope = &mut ctx.heap[scope_id]; - scope.next_unique_id_in_scope = variable_counter; - } - fn resolve_pending_control_flow_targets(&mut self, ctx: &mut Ctx) -> Result<(), ParseError> { for entry in &self.control_flow_stmts { let stmt = &ctx.heap[entry.statement];