Skip to main content

pine_sema/
scope.rs

1//! Name-kind classification and the global-only builtin list.
2//!
3//! Scopes themselves live in [`SymbolTable`](crate::SymbolTable): the analyzer
4//! resolves names against it directly, so there is no separate scope stack.
5
6/// What a declared name refers to. This drives rules like "you can't reassign a
7/// function" — only [`SymbolKind::Var`] is a reassignable value.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum SymbolKind {
10    /// A variable (`x = …`, loop variable, tuple binding, parameter).
11    Var,
12    Function,
13    Type,
14    Enum,
15    /// An import alias (`import foo/bar/1 as alias`).
16    Import,
17}
18
19impl SymbolKind {
20    /// A human-readable noun for diagnostics.
21    pub fn noun(self) -> &'static str {
22        match self {
23            SymbolKind::Var => "variable",
24            SymbolKind::Function => "function",
25            SymbolKind::Type => "type",
26            SymbolKind::Enum => "enum",
27            SymbolKind::Import => "import",
28        }
29    }
30
31    /// Pine keeps type declarations in a namespace separate from values, so a
32    /// UDT and a function/variable may share a name without colliding.
33    pub fn namespace(self) -> Namespace {
34        match self {
35            SymbolKind::Type | SymbolKind::Enum => Namespace::Type,
36            SymbolKind::Var | SymbolKind::Function | SymbolKind::Import => Namespace::Value,
37        }
38    }
39}
40
41/// The two namespaces a name can occupy; a redeclaration only collides within
42/// the same one.
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum Namespace {
45    Type,
46    Value,
47}
48
49/// Functions Pine only permits at **global** scope (never inside `if`, loops, or
50/// function bodies).
51const GLOBAL_ONLY_FUNCTIONS: &[&str] = &[
52    "plot",
53    "plotshape",
54    "plotchar",
55    "plotcandle",
56    "plotbar",
57    "plotarrow",
58    "fill",
59];
60
61/// May `name` only be called at global scope?
62pub fn is_global_only(name: &str) -> bool {
63    GLOBAL_ONLY_FUNCTIONS.contains(&name)
64}