1use std::{fmt, path::PathBuf, sync::Arc};
2
3use fxhash::FxHashMap;
4
5use crate::{
6 middle::{
7 rir::{self},
8 ty::{AdtDef, AdtKind, CodegenTy, TyKind},
9 type_graph::TypeGraph,
10 },
11 symbol::{DefId, FileId},
12 TagId,
13 tags::Tags,
14};
15
16#[derive(Default)]
17#[salsa::database(RirDatabaseStorage)]
18pub struct RootDatabase {
19 storage: salsa::Storage<RootDatabase>,
20}
21
22impl fmt::Debug for RootDatabase {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 f.debug_struct("RootDatabase").finish()
25 }
26}
27
28impl salsa::ParallelDatabase for RootDatabase {
29 fn snapshot(&self) -> salsa::Snapshot<RootDatabase> {
30 salsa::Snapshot::new(RootDatabase {
31 storage: self.storage.snapshot(),
32 })
33 }
34}
35
36#[salsa::query_group(RirDatabaseStorage)]
37pub trait RirDatabase {
38 #[salsa::input]
39 fn nodes(&self) -> Arc<FxHashMap<DefId, rir::Node>>;
40 #[salsa::input]
41 fn files(&self) -> Arc<FxHashMap<FileId, Arc<rir::File>>>;
42 #[salsa::input]
43 fn file_ids_map(&self) -> Arc<FxHashMap<Arc<PathBuf>, FileId>>;
44 #[salsa::input]
45 fn type_graph(&self) -> Arc<TypeGraph>;
46 #[salsa::input]
47 fn tags_map(&self) -> Arc<FxHashMap<TagId, Arc<Tags>>>;
48 #[salsa::input]
49 fn input_files(&self) -> Arc<Vec<FileId>>;
50
51 fn node(&self, def_id: DefId) -> Option<rir::Node>;
52 fn file(&self, file_id: FileId) -> Option<Arc<rir::File>>;
53 fn item(&self, def_id: DefId) -> Option<Arc<rir::Item>>;
54 fn expect_item(&self, def_id: DefId) -> Arc<rir::Item>;
55 fn codegen_item_ty(&self, ty: TyKind) -> CodegenTy;
56 fn codegen_const_ty(&self, ty: TyKind) -> CodegenTy;
57 fn codegen_ty(&self, def_id: DefId) -> CodegenTy;
58 fn service_methods(&self, def_id: DefId) -> Arc<[Arc<rir::Method>]>;
59}
60
61fn node(db: &dyn RirDatabase, def_id: DefId) -> Option<rir::Node> {
62 db.nodes().get(&def_id).cloned()
63}
64
65fn item(db: &dyn RirDatabase, def_id: DefId) -> Option<Arc<rir::Item>> {
66 let node = db.node(def_id);
67 match node {
68 Some(rir::Node {
69 kind: rir::NodeKind::Item(i),
70 ..
71 }) => Some(i),
72 None => None,
73 _ => panic!("{:?} is not an item", def_id),
74 }
75}
76
77fn expect_item(db: &dyn RirDatabase, def_id: DefId) -> Arc<rir::Item> {
78 db.item(def_id).unwrap()
79}
80
81fn file(db: &dyn RirDatabase, file_id: FileId) -> Option<Arc<rir::File>> {
82 db.files().get(&file_id).cloned()
83}
84
85fn codegen_item_ty(db: &dyn RirDatabase, ty: TyKind) -> CodegenTy {
86 ty.to_codegen_item_ty(db)
87}
88
89fn codegen_const_ty(db: &dyn RirDatabase, ty: TyKind) -> CodegenTy {
90 ty.to_codegen_const_ty(db)
91}
92
93fn codegen_ty(db: &dyn RirDatabase, did: DefId) -> CodegenTy {
94 let node = db.node(did).unwrap();
95 match &node.kind {
96 rir::NodeKind::Item(item) => {
97 let kind = match &**item {
98 rir::Item::Message(_) => AdtKind::Struct,
99 rir::Item::Enum(_) => AdtKind::Enum,
100 rir::Item::Service(_) => unimplemented!(),
101 rir::Item::NewType(t) => {
102 AdtKind::NewType(Arc::from(db.codegen_item_ty(t.ty.kind.clone())))
103 }
104 rir::Item::Const(c) => {
105 let mut ty = db.codegen_const_ty(c.ty.kind.clone());
106 if let CodegenTy::StaticRef(inner) = ty {
107 ty = CodegenTy::LazyStaticRef(inner)
108 }
109
110 return ty;
111 }
112 rir::Item::Mod(_) => unreachable!(),
113 };
114 CodegenTy::Adt(AdtDef { did, kind })
115 }
116 rir::NodeKind::Variant(_) => CodegenTy::Adt(AdtDef {
117 did: node.parent.unwrap(),
118 kind: AdtKind::Enum,
119 }),
120 rir::NodeKind::Field(_) => todo!(),
121 rir::NodeKind::Method(_) => todo!(),
122 rir::NodeKind::Arg(_) => todo!(),
123 }
124}
125
126fn service_methods(db: &dyn RirDatabase, def_id: DefId) -> Arc<[Arc<rir::Method>]> {
127 let item = db.expect_item(def_id);
128 let service = match &*item {
129 rir::Item::Service(s) => s,
130 _ => panic!(),
131 };
132 let methods = service
133 .extend
134 .iter()
135 .flat_map(|p| {
136 db.service_methods(p.did)
137 .iter()
138 .map(|m| match m.source {
139 rir::MethodSource::Extend(_) => m.clone(),
140 rir::MethodSource::Own => Arc::from(rir::Method {
141 source: rir::MethodSource::Extend(p.did),
142 ..(**m).clone()
143 }),
144 })
145 .collect::<Vec<_>>()
146 })
147 .chain(service.methods.iter().cloned());
148
149 Arc::from_iter(methods)
150}
151
152impl salsa::Database for RootDatabase {}