diff --git a/src/protocol/parser/pass_definitions.rs b/src/protocol/parser/pass_definitions.rs index 383d76f7d9ac00efcd9ea11af1bff108e3bcb3cb..16c5af1d7a6c63b60df29b87aa4c7b770bcada19 100644 --- a/src/protocol/parser/pass_definitions.rs +++ b/src/protocol/parser/pass_definitions.rs @@ -280,13 +280,15 @@ impl PassDefinitions { )?; // Consume block and the definition's scope - let body = self.consume_block_statement(module, iter, ctx)?; + let body_id = self.consume_block_statement(module, iter, ctx)?; + let scope_id = ctx.heap.alloc_scope(|this| Scope::new(this, ScopeAssociation::Definition(definition_id))); // Assign everything in the preallocated AST node let function = ctx.heap[definition_id].as_function_mut(); function.return_type = parser_type; function.parameters = parameters; - function.body = body; + function.scope = scope_id; + function.body = body_id; Ok(()) } @@ -315,12 +317,14 @@ impl PassDefinitions { let parameters = parameter_section.into_vec(); // Consume block - let body = self.consume_block_statement(module, iter, ctx)?; + let body_id = self.consume_block_statement(module, iter, ctx)?; + let scope_id = ctx.heap.alloc_scope(|this| Scope::new(this, ScopeAssociation::Definition(definition_id))); // Assign everything in the AST node let component = ctx.heap[definition_id].as_component_mut(); component.parameters = parameters; - component.body = body; + component.scope = scope_id; + component.body = body_id; Ok(()) } @@ -468,7 +472,7 @@ impl PassDefinitions { scope: ScopeId::new_invalid(), }; - let (false_body, false_body_scope_id) = if has_ident(&module.source, iter, KW_STMT_ELSE) { + let false_body = if has_ident(&module.source, iter, KW_STMT_ELSE) { iter.consume(); let false_body = IfStatementCase{ body: self.consume_statement(module, iter, ctx)?, @@ -476,9 +480,9 @@ impl PassDefinitions { }; let false_body_scope_id = false_body.scope; - (Some(false_body), Some(false_body_scope_id)) + Some(false_body) } else { - (None, None) + None }; // Construct AST elements @@ -496,13 +500,17 @@ impl PassDefinitions { next: StatementId::new_invalid(), }); let true_scope_id = ctx.heap.alloc_scope(|this| Scope::new(this, ScopeAssociation::If(if_stmt_id, true))); + let false_scope_id = if false_body.is_some() { + Some(ctx.heap.alloc_scope(|this| Scope::new(this, ScopeAssociation::If(if_stmt_id, false)))) + } else { + None + }; let if_stmt = &mut ctx.heap[if_stmt_id]; if_stmt.end_if = end_if_stmt_id; if_stmt.true_case.scope = true_scope_id; if let Some(false_case) = &mut if_stmt.false_case { - let false_scope_id = ctx.heap.alloc_scope(|this| Scope::new(this, ScopeAssociation::If(if_stmt_id, false))); - false_case.scope = false_scope_id + false_case.scope = false_scope_id.unwrap(); } return Ok(if_stmt_id); diff --git a/src/protocol/parser/pass_validation_linking.rs b/src/protocol/parser/pass_validation_linking.rs index 50501f7f680a8efd37dafad58ec0a94976dc3a29..c2fdd3dd0fccb697d51f2e26028c6da1414a67b2 100644 --- a/src/protocol/parser/pass_validation_linking.rs +++ b/src/protocol/parser/pass_validation_linking.rs @@ -225,7 +225,7 @@ impl Visitor for PassValidationLinking { let section = self.variable_buffer.start_section_initialized(&definition.parameters); for variable_idx in 0..section.len() { let variable_id = section[variable_idx]; - self.checked_at_single_scope_add_local(ctx, self.cur_scope, variable_idx as i32, variable_id)?; + self.checked_at_single_scope_add_local(ctx, self.cur_scope, -1, variable_id)?; } self.relative_pos_in_parent = section.len() as i32; @@ -264,7 +264,7 @@ impl Visitor for PassValidationLinking { let section = self.variable_buffer.start_section_initialized(&definition.parameters); for variable_idx in 0..section.len() { let variable_id = section[variable_idx]; - self.checked_at_single_scope_add_local(ctx, self.cur_scope, variable_idx as i32, variable_id)?; + self.checked_at_single_scope_add_local(ctx, self.cur_scope, -1, variable_id)?; } section.forget(); @@ -315,6 +315,9 @@ impl Visitor for PassValidationLinking { let expr_id = stmt.initial_expr; let variable_id = stmt.variable; + if ctx.heap[variable_id].identifier.value.as_str() == "counter" { + let a = 1; + } self.checked_add_local(ctx, self.cur_scope, self.relative_pos_in_parent, variable_id)?; assign_and_replace_next_stmt!(self, ctx, id.upcast().upcast()); @@ -570,6 +573,7 @@ impl Visitor for PassValidationLinking { self.in_select_guard = SelectStatementId::new_invalid(); // Visit the code associated with the guard + self.relative_pos_in_parent += 1; self.visit_stmt(ctx, case_body_id)?; self.pop_scope(old_scope); @@ -1351,6 +1355,10 @@ impl Visitor for PassValidationLinking { let mut is_binding_target = false; // Otherwise try to find it + if var_expr.identifier.value.as_str() == "new_value" { + let a = 0; // TODO: REMOVE! + } + if variable_id.is_none() { variable_id = self.find_variable(ctx, self.relative_pos_in_parent, &var_expr.identifier); } @@ -1471,7 +1479,7 @@ impl PassValidationLinking { let old_scope_id = self.cur_scope; let scope = &mut ctx.heap[pushed_scope_id]; - if is_top_level_scope { + if !is_top_level_scope { scope.parent = Some(old_scope_id); } @@ -1613,8 +1621,8 @@ impl PassValidationLinking { /// Adds a local variable to the current scope. It will also annotate the /// `Local` in the AST with its relative position in the block. - fn checked_add_local(&mut self, ctx: &mut Ctx, target_scope_id: ScopeId, target_relative_pos: i32, id: VariableId) -> Result<(), ParseError> { - let local = &ctx.heap[id]; + fn checked_add_local(&mut self, ctx: &mut Ctx, target_scope_id: ScopeId, target_relative_pos: i32, new_variable_id: VariableId) -> Result<(), ParseError> { + let new_variable = &ctx.heap[new_variable_id]; // We immediately go to the parent scope. We check the target scope // in the call at the end. That is also where we check for collisions @@ -1626,15 +1634,15 @@ impl PassValidationLinking { // Check for collisions for variable_id in scope.variables.iter().copied() { - let variable = &ctx.heap[variable_id]; - if variable.identifier == variable.identifier && - variable.this != id && - cur_relative_pos >= variable.relative_pos_in_parent { + let existing_variable = &ctx.heap[variable_id]; + if existing_variable.identifier == new_variable.identifier && + existing_variable.this != new_variable_id && + cur_relative_pos >= existing_variable.relative_pos_in_parent { return Err( ParseError::new_error_str_at_span( - &ctx.module().source, local.identifier.span, "Local variable name conflicts with another variable" + &ctx.module().source, new_variable.identifier.span, "Local variable name conflicts with another variable" ).with_info_str_at_span( - &ctx.module().source, variable.identifier.span, "Previous variable is found here" + &ctx.module().source, existing_variable.identifier.span, "Previous variable is found here" ) ); } @@ -1644,7 +1652,7 @@ impl PassValidationLinking { } // No collisions in any of the parent scope, attempt to add to scope - self.checked_at_single_scope_add_local(ctx, target_scope_id, target_relative_pos, id) + self.checked_at_single_scope_add_local(ctx, target_scope_id, target_relative_pos, new_variable_id) } /// Adds a local variable to the specified scope. Will check the specified