swamp_analyzer/
context.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 swamp_types::{TypeKind, TypeRef};
7
8/// `TypeRef` checking context
9#[derive(Debug, Clone)]
10pub struct TypeContext<'a> {
11    /// Expected type for the current expression
12    pub expected_type: Option<&'a TypeRef>,
13    pub has_lvalue_target: bool,
14}
15
16
17impl<'a> TypeContext<'a> {
18    #[must_use]
19    pub const fn new(expected_type: Option<&'a TypeRef>, has_lvalue_target: bool) -> Self {
20        Self {
21            expected_type,
22            has_lvalue_target,
23        }
24    }
25
26    pub(crate) const fn with_lvalue(&self) -> Self {
27        Self {
28            expected_type: self.expected_type,
29            has_lvalue_target: true,
30        }
31    }
32
33    pub(crate) const fn argument(&self, expected_type: &'a TypeRef) -> Self {
34        Self {
35            expected_type: Some(expected_type),
36            has_lvalue_target: self.has_lvalue_target,
37        }
38    }
39
40    pub(crate) const fn with_argument_anything(&self) -> Self {
41        Self {
42            expected_type: None,
43            has_lvalue_target: self.has_lvalue_target,
44        }
45    }
46
47    #[must_use]
48    pub const fn new_argument(required_type: &'a TypeRef, has_lvalue_target: bool) -> Self {
49        Self {
50            expected_type: Some(required_type),
51            has_lvalue_target,
52        }
53    }
54
55    #[must_use]
56    pub const fn new_unsure_argument(
57        expected_type: Option<&'a TypeRef>,
58        has_lvalue_target: bool,
59    ) -> Self {
60        Self {
61            expected_type,
62            has_lvalue_target,
63        }
64    }
65
66    #[must_use]
67    pub const fn new_anything_argument(has_lvalue_target: bool) -> Self {
68        Self {
69            expected_type: None,
70            has_lvalue_target,
71        }
72    }
73
74    #[must_use]
75    pub fn new_function(required_type: &'a TypeRef) -> Self {
76        Self {
77            expected_type: Some(required_type),
78            has_lvalue_target: required_type.collection_view_that_needs_explicit_storage(),
79        }
80    }
81
82    #[must_use]
83    pub const fn with_expected_type(
84        &self,
85        expected_type: Option<&'a TypeRef>,
86        has_lvalue_target: bool,
87    ) -> Self {
88        Self {
89            expected_type,
90            has_lvalue_target,
91        }
92    }
93
94    pub(crate) const fn we_know_expected_type(
95        &self,
96        found_type: &'a TypeRef,
97        has_lvalue_target: bool,
98    ) -> Self {
99        self.with_expected_type(Some(found_type), has_lvalue_target)
100    }
101
102    /// If the expected type is `Optional<T>`, returns `T`; otherwise returns the
103    /// original expected type.
104    #[must_use]
105    pub fn expected_type_or_optional_inner(&self) -> Self {
106        #[allow(clippy::bind_instead_of_map)]
107        let new_expected = self
108            .expected_type
109            .and_then(|expected| match expected.kind.as_ref() {
110                TypeKind::Optional(inner) => Some(inner),
111                _ => Some(expected),
112            });
113
114        Self {
115            expected_type: new_expected,
116            has_lvalue_target: self.has_lvalue_target,
117        }
118    }
119}