1use salsa::Database as Db;
2#[cfg(test)]
3use salsa::Setter;
4use salsa::Storage;
5use squawk_line_index::{LineIndex, find_newline};
6use squawk_syntax::{Parse, SourceFile};
7use std::sync::Arc;
8
9use crate::binder;
10use crate::binder::Binder;
11use crate::builtins::builtins_file;
12
13#[salsa::input]
14pub struct File {
15 #[returns(ref)]
16 pub content: Arc<str>,
17}
18
19#[salsa::tracked]
20pub fn parse(db: &dyn Db, file: File) -> Parse<SourceFile> {
21 SourceFile::parse(file.content(db))
22}
23
24#[salsa::tracked]
25pub fn line_index(db: &dyn Db, file: File) -> LineIndex {
26 LineIndex::new(file.content(db))
27}
28
29pub(crate) fn line_ending(db: &dyn Db, file: File) -> &'static str {
30 find_newline(file.content(db))
31 .map(|(_, line_ending)| line_ending)
32 .unwrap_or_default()
33 .as_str()
34}
35
36#[inline]
37pub(crate) fn list_files(db: &dyn Db, file: File) -> impl Iterator<Item = File> {
38 [Some(file), include_builtins(db).then(|| builtins_file(db))]
39 .into_iter()
40 .flatten()
41}
42
43#[salsa::tracked]
44pub(crate) fn bind(db: &dyn Db, file: File) -> Binder {
45 let result = parse(db, file);
46 let source_file = result.tree();
47 binder::bind(&source_file)
48}
49
50#[salsa::input(singleton)]
51pub(crate) struct Config {
52 pub(crate) include_builtins: bool,
54}
55
56#[salsa::tracked]
57pub(crate) fn include_builtins(db: &dyn Db) -> bool {
58 Config::get(db).include_builtins(db)
59}
60
61#[salsa::db]
62#[derive(Clone)]
63pub struct Database {
64 storage: Storage<Self>,
65}
66
67impl Default for Database {
68 fn default() -> Self {
69 let db = Self {
70 storage: Storage::default(),
71 };
72 Config::new(&db, true);
73 db
74 }
75}
76
77#[cfg(test)]
78pub(crate) fn set_include_builtins(db: &mut dyn Db, include_builtins: bool) {
79 Config::get(db)
80 .set_include_builtins(db)
81 .to(include_builtins);
82}
83
84impl salsa::Database for Database {}