1use std::collections::HashMap;
2use std::fmt::Debug;
3
4use enum_as_inner::EnumAsInner;
5use itertools::Itertools;
6use serde::{Deserialize, Serialize};
7
8use crate::codegen::write_ty;
9use crate::ir::pl;
10use crate::pr::{Span, Ty};
11use crate::semantic::write_pl;
12
13#[derive(Default, Serialize, Deserialize, Clone)]
15pub struct RootModule {
16 pub module: Module,
18
19 pub span_map: HashMap<usize, Span>,
20}
21
22#[derive(Default, PartialEq, Serialize, Deserialize, Clone)]
23pub struct Module {
24 pub names: HashMap<String, Decl>,
26
27 pub redirects: Vec<pl::Ident>,
38
39 pub shadowed: Option<Box<Decl>>,
41}
42
43#[derive(Debug, PartialEq, Default, Serialize, Deserialize, Clone)]
45pub struct Decl {
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub declared_at: Option<usize>,
48
49 pub kind: DeclKind,
50
51 #[serde(skip_serializing_if = "is_zero")]
54 pub order: usize,
55
56 #[serde(skip_serializing_if = "Vec::is_empty")]
57 pub annotations: Vec<pl::Annotation>,
58}
59
60#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumAsInner)]
62pub enum DeclKind {
63 Module(Module),
65
66 LayeredModules(Vec<Module>),
68
69 TableDecl(TableDecl),
70
71 InstanceOf(pl::Ident, Option<Ty>),
72
73 Column(usize),
77
78 Infer(Box<DeclKind>),
80
81 Expr(Box<pl::Expr>),
82
83 Ty(Ty),
84
85 QueryDef(pl::QueryDef),
86
87 Import(pl::Ident),
89}
90
91#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
92pub struct TableDecl {
93 pub ty: Option<Ty>,
97
98 pub expr: TableExpr,
99}
100
101#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumAsInner)]
102pub enum TableExpr {
103 RelationVar(Box<pl::Expr>),
105
106 LocalTable,
108
109 None,
111
112 Param(String),
114}
115
116#[derive(Clone, Eq, Debug, PartialEq, Serialize, Deserialize)]
117pub enum TableColumn {
118 Wildcard,
119 Single(Option<String>),
120}
121
122impl std::fmt::Debug for RootModule {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 self.module.fmt(f)
125 }
126}
127
128impl std::fmt::Debug for Module {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 let mut ds = f.debug_struct("Module");
131
132 if !self.redirects.is_empty() {
133 let redirects = self.redirects.iter().map(|x| x.to_string()).collect_vec();
134 ds.field("redirects", &redirects);
135 }
136
137 if self.names.len() < 15 {
138 ds.field("names", &DebugNames(&self.names));
139 } else {
140 ds.field("names", &format!("... {} entries ...", self.names.len()));
141 }
142 if self.shadowed.is_some() {
143 ds.field("shadowed", &"(hidden)");
144 }
145 ds.finish()
146 }
147}
148
149struct DebugNames<'a>(&'a HashMap<String, Decl>);
150
151impl std::fmt::Debug for DebugNames<'_> {
152 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
153 let mut dm = f.debug_map();
154 for (n, decl) in self.0.iter().sorted_by_key(|x| x.0) {
155 dm.entry(n, decl);
156 }
157 dm.finish()
158 }
159}
160
161impl Default for DeclKind {
162 fn default() -> Self {
163 DeclKind::Module(Module::default())
164 }
165}
166
167impl From<DeclKind> for Decl {
168 fn from(kind: DeclKind) -> Self {
169 Decl {
170 kind,
171 declared_at: None,
172 order: 0,
173 annotations: Vec::new(),
174 }
175 }
176}
177
178impl std::fmt::Display for Decl {
179 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180 std::fmt::Display::fmt(&self.kind, f)
181 }
182}
183
184impl std::fmt::Display for DeclKind {
185 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
186 match self {
187 Self::Module(arg0) => f.debug_tuple("Module").field(arg0).finish(),
188 Self::LayeredModules(arg0) => f.debug_tuple("LayeredModules").field(arg0).finish(),
189 Self::TableDecl(TableDecl { ty, expr }) => {
190 write!(
191 f,
192 "TableDecl: {} {expr:?}",
193 ty.as_ref().map(write_ty).unwrap_or_default()
194 )
195 }
196 Self::InstanceOf(arg0, _) => write!(f, "InstanceOf: {arg0}"),
197 Self::Column(arg0) => write!(f, "Column (target {arg0})"),
198 Self::Infer(arg0) => write!(f, "Infer (default: {arg0})"),
199 Self::Expr(arg0) => write!(f, "Expr: {}", write_pl(*arg0.clone())),
200 Self::Ty(arg0) => write!(f, "Ty: {}", write_ty(arg0)),
201 Self::QueryDef(_) => write!(f, "QueryDef"),
202 Self::Import(arg0) => write!(f, "Import {arg0}"),
203 }
204 }
205}
206
207fn is_zero(x: &usize) -> bool {
208 *x == 0
209}