Skip to main content

dada_ir_sym/ir/
variables.rs

1use dada_ir_ast::{
2    ast::{AstFunctionInput, AstSelfArg, Identifier, VariableDecl},
3    span::{Span, Spanned},
4};
5use dada_util::SalsaSerialize;
6
7use crate::{
8    check::scope::Scope,
9    ir::types::{SymGenericKind, SymGenericTerm},
10    prelude::Symbol,
11};
12
13use super::types::HasKind;
14
15/// Symbol for a generic parameter or local variable.
16#[derive(SalsaSerialize)]
17#[salsa::tracked(debug)]
18pub struct SymVariable<'db> {
19    pub kind: SymGenericKind,
20    pub name: Option<Identifier<'db>>,
21    pub span: Span<'db>,
22}
23
24impl<'db> SymVariable<'db> {
25    /// New symbol for a local variable
26    pub fn new_local(db: &'db dyn crate::Db, id: Identifier<'db>, span: Span<'db>) -> Self {
27        Self::new(db, SymGenericKind::Place, Some(id), span)
28    }
29
30    pub fn into_generic_term(
31        self,
32        db: &'db dyn crate::Db,
33        scope: &Scope<'_, 'db>,
34    ) -> SymGenericTerm<'db> {
35        assert!(
36            scope.generic_sym_in_scope(db, self),
37            "generic symbol for `{self:?}` not in scope"
38        );
39        SymGenericTerm::var(db, self)
40    }
41}
42
43impl<'db> HasKind<'db> for SymVariable<'db> {
44    fn has_kind(&self, db: &'db dyn crate::Db, kind: SymGenericKind) -> bool {
45        self.kind(db) == kind
46    }
47}
48
49impl<'db> Spanned<'db> for SymVariable<'db> {
50    fn span(&self, db: &'db dyn dada_ir_ast::Db) -> Span<'db> {
51        SymVariable::span(*self, db)
52    }
53}
54
55impl std::fmt::Display for SymVariable<'_> {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        salsa::with_attached_database(|db| match self.name(db) {
58            Some(name) => write!(f, "{name}"),
59            None => write!(f, "{kind}", kind = self.kind(db)),
60        })
61        .unwrap_or_else(|| std::fmt::Debug::fmt(self, f))
62    }
63}
64
65/// Many of our types can be created from a variable
66pub trait FromVar<'db> {
67    fn var(db: &'db dyn crate::Db, var: SymVariable<'db>) -> Self;
68}
69
70impl<'db> Symbol<'db> for AstFunctionInput<'db> {
71    type Output = SymVariable<'db>;
72
73    fn symbol(self, db: &'db dyn crate::Db) -> SymVariable<'db> {
74        match self {
75            AstFunctionInput::SelfArg(ast_self_arg) => ast_self_arg.symbol(db),
76            AstFunctionInput::Variable(variable_decl) => variable_decl.symbol(db),
77        }
78    }
79}
80
81#[salsa::tracked]
82impl<'db> Symbol<'db> for VariableDecl<'db> {
83    type Output = SymVariable<'db>;
84
85    #[salsa::tracked]
86    fn symbol(self, db: &'db dyn crate::Db) -> SymVariable<'db> {
87        SymVariable::new(
88            db,
89            SymGenericKind::Place,
90            Some(self.name(db).id),
91            self.name(db).span,
92        )
93    }
94}
95
96#[salsa::tracked]
97impl<'db> Symbol<'db> for AstSelfArg<'db> {
98    type Output = SymVariable<'db>;
99
100    #[salsa::tracked]
101    fn symbol(self, db: &'db dyn crate::Db) -> SymVariable<'db> {
102        SymVariable::new(
103            db,
104            SymGenericKind::Place,
105            Some(Identifier::self_ident(db)),
106            self.self_span(db),
107        )
108    }
109}