use enum_as_inner::EnumAsInner;
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt::Debug;
use prqlc_ast::{Span, Ty};
use crate::codegen::write_ty;
use crate::ir::pl::*;
use crate::semantic::write_pl;
#[derive(Default, Serialize, Deserialize, Clone)]
pub struct RootModule {
pub module: Module,
pub span_map: HashMap<usize, Span>,
}
#[derive(Default, PartialEq, Serialize, Deserialize, Clone)]
pub struct Module {
pub names: HashMap<String, Decl>,
pub redirects: Vec<Ident>,
pub shadowed: Option<Box<Decl>>,
}
#[derive(Debug, PartialEq, Default, Serialize, Deserialize, Clone)]
pub struct Decl {
#[serde(skip_serializing_if = "Option::is_none")]
pub declared_at: Option<usize>,
pub kind: DeclKind,
#[serde(skip_serializing_if = "is_zero")]
pub order: usize,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub annotations: Vec<Annotation>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumAsInner)]
pub enum DeclKind {
Module(Module),
LayeredModules(Vec<Module>),
TableDecl(TableDecl),
InstanceOf(Ident, Option<Ty>),
Column(usize),
Infer(Box<DeclKind>),
Expr(Box<Expr>),
Ty(Ty),
QueryDef(QueryDef),
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct TableDecl {
pub ty: Option<Ty>,
pub expr: TableExpr,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumAsInner)]
pub enum TableExpr {
RelationVar(Box<Expr>),
LocalTable,
None,
Param(String),
}
#[derive(Clone, Eq, Debug, PartialEq, Serialize, Deserialize)]
pub enum TableColumn {
Wildcard,
Single(Option<String>),
}
impl std::fmt::Debug for RootModule {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.module.fmt(f)
}
}
impl std::fmt::Debug for Module {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("Module");
if !self.redirects.is_empty() {
let redirects = self.redirects.iter().map(|x| x.to_string()).collect_vec();
ds.field("redirects", &redirects);
}
if self.names.len() < 15 {
ds.field("names", &DebugNames(&self.names));
} else {
ds.field("names", &format!("... {} entries ...", self.names.len()));
}
if self.shadowed.is_some() {
ds.field("shadowed", &"(hidden)");
}
ds.finish()
}
}
struct DebugNames<'a>(&'a HashMap<String, Decl>);
impl<'a> std::fmt::Debug for DebugNames<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut dm = f.debug_map();
for (n, decl) in self.0.iter().sorted_by_key(|x| x.0) {
dm.entry(n, decl);
}
dm.finish()
}
}
impl Default for DeclKind {
fn default() -> Self {
DeclKind::Module(Module::default())
}
}
impl From<DeclKind> for Decl {
fn from(kind: DeclKind) -> Self {
Decl {
kind,
declared_at: None,
order: 0,
annotations: Vec::new(),
}
}
}
impl std::fmt::Display for Decl {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.kind, f)
}
}
impl std::fmt::Display for DeclKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Module(arg0) => f.debug_tuple("Module").field(arg0).finish(),
Self::LayeredModules(arg0) => f.debug_tuple("LayeredModules").field(arg0).finish(),
Self::TableDecl(TableDecl { ty, expr }) => {
write!(
f,
"TableDecl: {} {expr:?}",
ty.as_ref().map(write_ty).unwrap_or_default()
)
}
Self::InstanceOf(arg0, _) => write!(f, "InstanceOf: {arg0}"),
Self::Column(arg0) => write!(f, "Column (target {arg0})"),
Self::Infer(arg0) => write!(f, "Infer (default: {arg0})"),
Self::Expr(arg0) => write!(f, "Expr: {}", write_pl(*arg0.clone())),
Self::Ty(arg0) => write!(f, "Ty: {}", write_ty(arg0)),
Self::QueryDef(_) => write!(f, "QueryDef"),
}
}
}
fn is_zero(x: &usize) -> bool {
*x == 0
}