pine_sema/lib.rs
1//! Semantic analysis for Pine Script — a static pre-check that runs after
2//! parsing and before execution.
3//!
4//! # Example
5//!
6//! ```
7//! use pine_ast::Program;
8//! use pine_lexer::Lexer;
9//! use pine_parser::Parser;
10//!
11//! let src = "x = clse + 1\n"; // typo: `clse`
12//! let tokens = Lexer::new(src).tokenize().unwrap();
13//! let program = Program::new(Parser::new(tokens).parse().unwrap());
14//!
15//! use std::collections::HashMap;
16//! use pine_core::DefaultPineOutput;
17//! use pine_interpreter::Value;
18//!
19//! // The built-ins the runtime registers; here just `close`.
20//! let mut builtins: HashMap<String, Value<DefaultPineOutput>> = HashMap::new();
21//! builtins.insert("close".to_string(), Value::Na);
22//!
23//! let errors = pine_sema::analyze(&program, &builtins, None);
24//! assert_eq!(errors.len(), 1);
25//! assert_eq!(errors[0].rule, "undeclared-variable");
26//! ```
27
28mod analyzer;
29mod scope;
30mod symbols;
31
32pub use analyzer::Analyzer;
33pub use pine_core::LibraryLoader;
34pub use pine_diagnostics::{Diagnostic, Severity};
35pub use scope::SymbolKind;
36pub use symbols::{FileId, ScopeId, ScopeKind, Symbol, SymbolId, SymbolTable};
37
38use pine_ast::Program;
39use pine_core::PineOutput;
40use pine_interpreter::Value;
41use std::collections::HashMap;
42
43/// Run semantic analysis over a parsed program and return every error found.
44/// An empty result means the program passed all implemented semantic checks.
45///
46/// `builtins` is the runtime's registered built-ins (from
47/// `pine_builtins::register_namespace_objects` plus the per-bar variables) — the
48/// names that resolve without a user declaration. It is taken as the full value
49/// map so later passes can inspect the objects' types.
50///
51/// `loader`, when present, resolves `import`ed libraries so `alias.export`
52/// resolves cross-file (and a library's own errors are reported, tagged with the
53/// library path). Without it, imports declare only the alias.
54pub fn analyze<O: PineOutput>(
55 program: &Program,
56 builtins: &HashMap<String, Value<O>>,
57 loader: Option<&dyn LibraryLoader>,
58) -> Vec<Diagnostic> {
59 Analyzer::new(builtins, loader).analyze(program)
60}
61
62/// Analyze a program and also return the [`SymbolTable`] reconstructed from the
63/// same walk — the durable declarations a tool (language server) queries.
64pub fn analyze_with_symbols<O: PineOutput>(
65 program: &Program,
66 builtins: &HashMap<String, Value<O>>,
67 loader: Option<&dyn LibraryLoader>,
68) -> (Vec<Diagnostic>, SymbolTable) {
69 Analyzer::new(builtins, loader).into_analysis(program)
70}