swamp_semantic/
type_var_stack.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5
6use crate::SemanticError;
7use crate::instantiator::TypeVariableScope;
8use seq_map::SeqMap;
9use swamp_types::Type;
10
11#[derive(Debug, Default)]
12pub struct SemanticContext {
13    type_variable_scopes: Vec<TypeVariableScope>,
14}
15
16impl SemanticContext {
17    pub fn push_type_scope(&mut self) {
18        self.type_variable_scopes
19            .push(TypeVariableScope::new(SeqMap::new()));
20    }
21
22    pub fn push_type_scope_with_variables(
23        &mut self,
24        type_variables: &[String],
25    ) -> Result<(), SemanticError> {
26        self.push_type_scope();
27        for type_variable in type_variables {
28            self.declare_type_variable(type_variable)?;
29        }
30        Ok(())
31    }
32
33    pub fn pop_type_scope(&mut self) {
34        assert!(!self.type_variable_scopes.is_empty());
35        self.type_variable_scopes.pop();
36    }
37
38    /// # Errors
39    ///
40    /// # Panics
41    /// if no stack is present
42    pub fn declare_type_variable(&mut self, name: &str) -> Result<(), SemanticError> {
43        self.type_variable_scopes.last_mut().map_or_else(
44            || {
45                panic!("Error: No active type variable scope!");
46            },
47            |current_scope| current_scope.add_type_variable(name),
48        )
49    }
50
51    #[must_use]
52    pub fn resolve_type_variable(&self, name: &str) -> Option<Type> {
53        for scope in self.type_variable_scopes.iter().rev() {
54            if let Some(found_type) = scope.internal_get_type(&name) {
55                return Some(found_type.clone());
56            }
57        }
58        None
59    }
60}