leo_passes/type_checking/
scope_state.rs

1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use indexmap::IndexMap;
18use leo_ast::{Location, Variant};
19use leo_span::Symbol;
20
21pub struct ScopeState {
22    /// The name of the function that we are currently traversing.
23    pub(crate) function: Option<Symbol>,
24    /// The variant of the function that we are currently traversing.
25    pub(crate) variant: Option<Variant>,
26    /// Whether or not the function that we are currently traversing has a return statement.
27    pub(crate) has_return: bool,
28    /// Current program name.
29    pub(crate) program_name: Option<Symbol>,
30    /// Current module name.
31    pub(crate) module_name: Vec<Symbol>,
32    /// Whether or not we are currently traversing a stub.
33    pub(crate) is_stub: bool,
34    /// The futures that must be propagated to an async function.
35    /// We only expect futures in the top level program scope at this stage so just refer to them by their names.
36    pub(crate) futures: IndexMap<Symbol, Location>,
37    /// Whether the finalize caller has called the finalize function.
38    pub(crate) has_called_finalize: bool,
39    /// Whether this function already contains an `async` block.
40    pub(crate) already_contains_an_async_block: bool,
41    /// Whether we are currently traversing a conditional statement.
42    pub(crate) is_conditional: bool,
43    /// Location of most recent external call that produced a future.
44    pub(crate) call_location: Option<Location>,
45    /// Whether we are currently traversing a constructor.
46    pub(crate) is_constructor: bool,
47}
48
49impl ScopeState {
50    /// Initializes a new `ScopeState`.
51    pub fn new() -> Self {
52        Self {
53            function: None,
54            variant: None,
55            has_return: false,
56            program_name: None,
57            module_name: vec![],
58            is_stub: false,
59            futures: IndexMap::new(),
60            has_called_finalize: false,
61            already_contains_an_async_block: false,
62            is_conditional: false,
63            call_location: None,
64            is_constructor: false,
65        }
66    }
67
68    /// Resets the scope state to a valid starting state, before traversing a function or constructor.
69    pub fn reset(&mut self) {
70        self.function = None;
71        self.variant = None;
72        self.has_return = false;
73        self.is_stub = false;
74        self.has_called_finalize = false;
75        self.is_conditional = false;
76        self.call_location = None;
77        self.is_constructor = false;
78        self.already_contains_an_async_block = false;
79        self.futures = IndexMap::new();
80    }
81
82    /// Get the current location.
83    pub fn location(&self) -> Location {
84        let function_path = self
85            .module_name
86            .iter()
87            .cloned()
88            .chain(std::iter::once(
89                self.function.expect("Only call ScopeState::location when visiting a function or function stub."),
90            ))
91            .collect::<Vec<Symbol>>();
92
93        Location::new(
94            self.program_name.expect("Only call ScopeState::location when visiting a function or function stub."),
95            function_path,
96        )
97    }
98}