1use core::fmt;
4use std::{
5    collections::BTreeMap,
6    ops::{Deref, Range},
7    sync::Arc,
8};
9
10use rustc_hash::FxHashMap;
11use serde::{Deserialize, Serialize};
12use tinymist_derive::DeclEnum;
13use tinymist_std::DefId;
14use tinymist_world::package::PackageSpec;
15use typst::{
16    foundations::{Element, Func, Module, Type, Value},
17    syntax::{Span, SyntaxNode},
18    utils::LazyHash,
19};
20
21use crate::{
22    adt::interner::impl_internable,
23    docs::DocString,
24    prelude::*,
25    ty::{InsTy, Interned, SelectTy, Ty, TypeVar},
26};
27
28use super::{ExprDescriber, ExprPrinter};
29
30#[derive(Debug, Clone, Hash)]
35pub struct ExprInfo(Arc<LazyHash<ExprInfoRepr>>);
36
37impl ExprInfo {
38    pub fn new(repr: ExprInfoRepr) -> Self {
44        Self(Arc::new(LazyHash::new(repr)))
45    }
46}
47
48impl Deref for ExprInfo {
49    type Target = Arc<LazyHash<ExprInfoRepr>>;
50
51    fn deref(&self) -> &Self::Target {
52        &self.0
53    }
54}
55
56#[derive(Debug)]
61pub struct ExprInfoRepr {
62    pub fid: TypstFileId,
64    pub revision: usize,
66    pub source: Source,
68    pub root: Expr,
70    pub module_docstring: Arc<DocString>,
72    pub exports: Arc<LazyHash<LexicalScope>>,
74    pub imports: FxHashMap<TypstFileId, Arc<LazyHash<LexicalScope>>>,
76    pub exprs: FxHashMap<Span, Expr>,
78    pub resolves: FxHashMap<Span, Interned<RefExpr>>,
80    pub docstrings: FxHashMap<DeclExpr, Arc<DocString>>,
82}
83
84impl std::hash::Hash for ExprInfoRepr {
85    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
86        self.revision.hash(state);
89        self.source.hash(state);
90        self.root.hash(state);
91        self.exports.hash(state);
92        let mut resolves = self.resolves.iter().collect::<Vec<_>>();
93        resolves.sort_by_key(|(fid, _)| fid.into_raw());
94        resolves.hash(state);
95        let mut imports = self.imports.iter().collect::<Vec<_>>();
96        imports.sort_by_key(|(fid, _)| *fid);
97        imports.hash(state);
98    }
99}
100
101impl ExprInfoRepr {
102    pub fn get_def(&self, decl: &Interned<Decl>) -> Option<Expr> {
104        if decl.is_def() {
105            return Some(Expr::Decl(decl.clone()));
106        }
107        let resolved = self.resolves.get(&decl.span())?;
108        Some(Expr::Ref(resolved.clone()))
109    }
110
111    pub fn get_refs(
113        &self,
114        decl: Interned<Decl>,
115    ) -> impl Iterator<Item = (&Span, &Interned<RefExpr>)> {
116        let of = Some(Expr::Decl(decl.clone()));
117        self.resolves
118            .iter()
119            .filter(move |(_, r)| match (decl.as_ref(), r.decl.as_ref()) {
120                (Decl::Label(..), Decl::Label(..)) => r.decl == decl,
121                (Decl::Label(..), Decl::ContentRef(..)) => r.decl.name() == decl.name(),
122                (Decl::Label(..), _) => false,
123                _ => r.decl == decl || r.root == of,
124            })
125    }
126
127    pub fn is_exported(&self, decl: &Interned<Decl>) -> bool {
129        let of = Expr::Decl(decl.clone());
130        self.exports
131            .get(decl.name())
132            .is_some_and(|export| match export {
133                Expr::Ref(ref_expr) => ref_expr.root == Some(of),
134                exprt => *exprt == of,
135            })
136    }
137
138    #[allow(dead_code)]
140    fn show(&self) {
141        use std::io::Write;
142        let vpath = self
143            .fid
144            .vpath()
145            .resolve(Path::new("target/exprs/"))
146            .unwrap();
147        let root = vpath.with_extension("root.expr");
148        std::fs::create_dir_all(root.parent().unwrap()).unwrap();
149        std::fs::write(root, format!("{}", self.root)).unwrap();
150        let scopes = vpath.with_extension("scopes.expr");
151        std::fs::create_dir_all(scopes.parent().unwrap()).unwrap();
152        {
153            let mut scopes = std::fs::File::create(scopes).unwrap();
154            for (span, expr) in self.exprs.iter() {
155                writeln!(scopes, "{span:?} -> {expr}").unwrap();
156            }
157        }
158        let imports = vpath.with_extension("imports.expr");
159        std::fs::create_dir_all(imports.parent().unwrap()).unwrap();
160        std::fs::write(imports, format!("{:#?}", self.imports)).unwrap();
161        let exports = vpath.with_extension("exports.expr");
162        std::fs::create_dir_all(exports.parent().unwrap()).unwrap();
163        std::fs::write(exports, format!("{:#?}", self.exports)).unwrap();
164    }
165}
166
167#[derive(Debug, Clone, PartialEq, Eq, Hash)]
172pub enum Expr {
173    Block(Interned<Vec<Expr>>),
175    Array(Interned<ArgsExpr>),
177    Dict(Interned<ArgsExpr>),
179    Args(Interned<ArgsExpr>),
181    Pattern(Interned<Pattern>),
183    Element(Interned<ElementExpr>),
185    Unary(Interned<UnExpr>),
187    Binary(Interned<BinExpr>),
189    Apply(Interned<ApplyExpr>),
191    Func(Interned<FuncExpr>),
193    Let(Interned<LetExpr>),
195    Show(Interned<ShowExpr>),
197    Set(Interned<SetExpr>),
199    Ref(Interned<RefExpr>),
201    ContentRef(Interned<ContentRefExpr>),
203    Select(Interned<SelectExpr>),
205    Import(Interned<ImportExpr>),
207    Include(Interned<IncludeExpr>),
209    Contextual(Interned<Expr>),
211    Conditional(Interned<IfExpr>),
213    WhileLoop(Interned<WhileExpr>),
215    ForLoop(Interned<ForExpr>),
217    Type(Ty),
219    Decl(DeclExpr),
221    Star,
223}
224
225impl Expr {
226    pub fn repr(&self) -> EcoString {
228        let mut s = EcoString::new();
229        let _ = ExprDescriber::new(&mut s).write_expr(self);
230        s
231    }
232
233    pub fn span(&self) -> Span {
235        match self {
236            Expr::Decl(decl) => decl.span(),
237            Expr::Select(select) => select.span,
238            Expr::Apply(apply) => apply.span,
239            _ => Span::detached(),
240        }
241    }
242
243    pub fn file_id(&self) -> Option<TypstFileId> {
245        match self {
246            Expr::Decl(decl) => decl.file_id(),
247            _ => self.span().id(),
248        }
249    }
250
251    pub fn is_defined(&self) -> bool {
253        match self {
254            Expr::Ref(refs) => refs.root.is_some() || refs.term.is_some(),
255            Expr::Decl(decl) => decl.is_def(),
256            _ => false,
258        }
259    }
260}
261
262impl fmt::Display for Expr {
263    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
264        ExprPrinter::new(f).write_expr(self)
265    }
266}
267
268pub type LexicalScope = rpds::RedBlackTreeMapSync<Interned<str>, Expr>;
272
273#[derive(Debug, Clone)]
278pub enum ExprScope {
279    Lexical(LexicalScope),
281    Module(Module),
283    Func(Func),
285    Type(Type),
287}
288
289impl ExprScope {
290    pub fn empty() -> Self {
292        ExprScope::Lexical(LexicalScope::default())
293    }
294
295    pub fn is_empty(&self) -> bool {
297        match self {
298            ExprScope::Lexical(scope) => scope.is_empty(),
299            ExprScope::Module(module) => is_empty_scope(module.scope()),
300            ExprScope::Func(func) => func.scope().is_none_or(is_empty_scope),
301            ExprScope::Type(ty) => is_empty_scope(ty.scope()),
302        }
303    }
304
305    pub fn get(&self, name: &Interned<str>) -> (Option<Expr>, Option<Ty>) {
308        let (of, val) = match self {
309            ExprScope::Lexical(scope) => {
310                crate::log_debug_ct!("evaluating: {name:?} in {scope:?}");
311                (scope.get(name).cloned(), None)
312            }
313            ExprScope::Module(module) => {
314                let v = module.scope().get(name);
315                (None, v)
319            }
320            ExprScope::Func(func) => (None, func.scope().unwrap().get(name)),
321            ExprScope::Type(ty) => (None, ty.scope().get(name)),
322        };
323
324        (
328            of,
329            val.cloned()
330                .map(|val| Ty::Value(InsTy::new(val.read().to_owned()))),
331        )
332    }
333
334    pub fn merge_into(&self, exports: &mut LexicalScope) {
336        match self {
337            ExprScope::Lexical(scope) => {
338                for (name, expr) in scope.iter() {
339                    exports.insert_mut(name.clone(), expr.clone());
340                }
341            }
342            ExprScope::Module(module) => {
343                crate::log_debug_ct!("imported: {module:?}");
344                let v = Interned::new(Ty::Value(InsTy::new(Value::Module(module.clone()))));
345                for (name, _) in module.scope().iter() {
346                    let name: Interned<str> = name.into();
347                    exports.insert_mut(name.clone(), select_of(v.clone(), name));
348                }
349            }
350            ExprScope::Func(func) => {
351                if let Some(scope) = func.scope() {
352                    let v = Interned::new(Ty::Value(InsTy::new(Value::Func(func.clone()))));
353                    for (name, _) in scope.iter() {
354                        let name: Interned<str> = name.into();
355                        exports.insert_mut(name.clone(), select_of(v.clone(), name));
356                    }
357                }
358            }
359            ExprScope::Type(ty) => {
360                let v = Interned::new(Ty::Value(InsTy::new(Value::Type(*ty))));
361                for (name, _) in ty.scope().iter() {
362                    let name: Interned<str> = name.into();
363                    exports.insert_mut(name.clone(), select_of(v.clone(), name));
364                }
365            }
366        }
367    }
368}
369
370fn select_of(source: Interned<Ty>, name: Interned<str>) -> Expr {
371    Expr::Type(Ty::Select(SelectTy::new(source, name)))
372}
373
374#[derive(Debug, Default, Clone, Copy, Hash, Serialize, Deserialize)]
376#[serde(rename_all = "camelCase")]
377pub enum DefKind {
378    #[default]
380    Constant,
381    Function,
383    Variable,
385    Module,
387    Struct,
389    Reference,
391}
392
393impl fmt::Display for DefKind {
394    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395        match self {
396            Self::Constant => write!(f, "constant"),
397            Self::Function => write!(f, "function"),
398            Self::Variable => write!(f, "variable"),
399            Self::Module => write!(f, "module"),
400            Self::Struct => write!(f, "struct"),
401            Self::Reference => write!(f, "reference"),
402        }
403    }
404}
405
406pub type DeclExpr = Interned<Decl>;
408
409#[derive(Clone, PartialEq, Eq, Hash, DeclEnum)]
411pub enum Decl {
412    Func(SpannedDecl),
414    ImportAlias(SpannedDecl),
416    Var(SpannedDecl),
418    IdentRef(SpannedDecl),
420    Module(ModuleDecl),
422    ModuleAlias(SpannedDecl),
424    PathStem(SpannedDecl),
426    ImportPath(SpannedDecl),
428    IncludePath(SpannedDecl),
430    Import(SpannedDecl),
432    ContentRef(SpannedDecl),
434    Label(SpannedDecl),
436    StrName(SpannedDecl),
438    ModuleImport(SpanDecl),
440    Closure(SpanDecl),
442    Pattern(SpanDecl),
444    Spread(SpanDecl),
446    Content(SpanDecl),
448    Constant(SpanDecl),
450    BibEntry(NameRangeDecl),
452    Docs(DocsDecl),
454    Generated(GeneratedDecl),
456}
457
458impl Decl {
459    pub fn func(ident: ast::Ident) -> Self {
461        Self::Func(SpannedDecl {
462            name: ident.get().into(),
463            at: ident.span(),
464        })
465    }
466
467    pub fn lit(name: &str) -> Self {
469        Self::Var(SpannedDecl {
470            name: name.into(),
471            at: Span::detached(),
472        })
473    }
474
475    pub fn lit_(name: Interned<str>) -> Self {
477        Self::Var(SpannedDecl {
478            name,
479            at: Span::detached(),
480        })
481    }
482
483    pub fn var(ident: ast::Ident) -> Self {
485        Self::Var(SpannedDecl {
486            name: ident.get().into(),
487            at: ident.span(),
488        })
489    }
490
491    pub fn import_alias(ident: ast::Ident) -> Self {
493        Self::ImportAlias(SpannedDecl {
494            name: ident.get().into(),
495            at: ident.span(),
496        })
497    }
498
499    pub fn ident_ref(ident: ast::Ident) -> Self {
501        Self::IdentRef(SpannedDecl {
502            name: ident.get().into(),
503            at: ident.span(),
504        })
505    }
506
507    pub fn math_ident_ref(ident: ast::MathIdent) -> Self {
509        Self::IdentRef(SpannedDecl {
510            name: ident.get().into(),
511            at: ident.span(),
512        })
513    }
514
515    pub fn module(fid: TypstFileId) -> Self {
517        let name = {
518            let stem = fid.vpath().as_rooted_path().file_stem();
519            stem.and_then(|s| Some(Interned::new_str(s.to_str()?)))
520                .unwrap_or_default()
521        };
522        Self::Module(ModuleDecl { name, fid })
523    }
524
525    pub fn module_with_name(name: Interned<str>, fid: TypstFileId) -> Self {
527        Self::Module(ModuleDecl { name, fid })
528    }
529
530    pub fn module_alias(ident: ast::Ident) -> Self {
532        Self::ModuleAlias(SpannedDecl {
533            name: ident.get().into(),
534            at: ident.span(),
535        })
536    }
537
538    pub fn import(ident: ast::Ident) -> Self {
540        Self::Import(SpannedDecl {
541            name: ident.get().into(),
542            at: ident.span(),
543        })
544    }
545
546    pub fn label(name: &str, at: Span) -> Self {
548        Self::Label(SpannedDecl {
549            name: name.into(),
550            at,
551        })
552    }
553
554    pub fn ref_(ident: ast::Ref) -> Self {
556        Self::ContentRef(SpannedDecl {
557            name: ident.target().into(),
558            at: ident.span(),
559        })
560    }
561
562    pub fn str_name(s: SyntaxNode, name: &str) -> Decl {
564        Self::StrName(SpannedDecl {
565            name: name.into(),
566            at: s.span(),
567        })
568    }
569
570    pub fn calc_path_stem(s: &str) -> Interned<str> {
576        use std::str::FromStr;
577        let name = if s.starts_with('@') {
578            let spec = PackageSpec::from_str(s).ok();
579            spec.map(|spec| Interned::new_str(spec.name.as_str()))
580        } else {
581            let stem = Path::new(s).file_stem();
582            stem.and_then(|stem| Some(Interned::new_str(stem.to_str()?)))
583        };
584        name.unwrap_or_default()
585    }
586
587    pub fn path_stem(s: SyntaxNode, name: Interned<str>) -> Self {
589        Self::PathStem(SpannedDecl { name, at: s.span() })
590    }
591
592    pub fn import_path(s: Span, name: Interned<str>) -> Self {
594        Self::ImportPath(SpannedDecl { name, at: s })
595    }
596
597    pub fn include_path(s: Span, name: Interned<str>) -> Self {
599        Self::IncludePath(SpannedDecl { name, at: s })
600    }
601
602    pub fn module_import(s: Span) -> Self {
604        Self::ModuleImport(SpanDecl(s))
605    }
606
607    pub fn closure(s: Span) -> Self {
609        Self::Closure(SpanDecl(s))
610    }
611
612    pub fn pattern(s: Span) -> Self {
614        Self::Pattern(SpanDecl(s))
615    }
616
617    pub fn spread(s: Span) -> Self {
619        Self::Spread(SpanDecl(s))
620    }
621
622    pub fn content(s: Span) -> Self {
624        Self::Content(SpanDecl(s))
625    }
626
627    pub fn constant(s: Span) -> Self {
629        Self::Constant(SpanDecl(s))
630    }
631
632    pub fn docs(base: Interned<Decl>, var: Interned<TypeVar>) -> Self {
635        Self::Docs(DocsDecl { base, var })
636    }
637
638    pub fn generated(def_id: DefId) -> Self {
640        Self::Generated(GeneratedDecl(def_id))
641    }
642
643    pub fn bib_entry(
645        name: Interned<str>,
646        fid: TypstFileId,
647        name_range: Range<usize>,
648        range: Option<Range<usize>>,
649    ) -> Self {
650        Self::BibEntry(NameRangeDecl {
651            name,
652            at: Box::new((fid, name_range, range)),
653        })
654    }
655
656    pub fn is_def(&self) -> bool {
659        matches!(
660            self,
661            Self::Func(..)
662                | Self::BibEntry(..)
663                | Self::Closure(..)
664                | Self::Var(..)
665                | Self::Label(..)
666                | Self::StrName(..)
667                | Self::Module(..)
668                | Self::ModuleImport(..)
669                | Self::PathStem(..)
670                | Self::ImportPath(..)
671                | Self::IncludePath(..)
672                | Self::Spread(..)
673                | Self::Generated(..)
674        )
675    }
676
677    pub fn kind(&self) -> DefKind {
679        use Decl::*;
680        match self {
681            ModuleAlias(..) | Module(..) | PathStem(..) | ImportPath(..) | IncludePath(..) => {
682                DefKind::Module
683            }
684            Func(..) | Closure(..) => DefKind::Function,
686            Label(..) | BibEntry(..) | ContentRef(..) => DefKind::Reference,
687            IdentRef(..) | ImportAlias(..) | Import(..) | Var(..) => DefKind::Variable,
688            Pattern(..) | Docs(..) | Generated(..) | Constant(..) | StrName(..)
689            | ModuleImport(..) | Content(..) | Spread(..) => DefKind::Constant,
690        }
691    }
692
693    pub fn file_id(&self) -> Option<TypstFileId> {
695        match self {
696            Self::Module(ModuleDecl { fid, .. }) => Some(*fid),
697            Self::BibEntry(NameRangeDecl { at, .. }) => Some(at.0),
698            that => that.span().id(),
699        }
700    }
701
702    pub fn full_range(&self) -> Option<Range<usize>> {
704        if let Decl::BibEntry(decl) = self {
705            return decl.at.2.clone();
706        }
707
708        None
709    }
710
711    pub fn as_def(this: &Interned<Self>, val: Option<Ty>) -> Interned<RefExpr> {
713        let def: Expr = this.clone().into();
714        Interned::new(RefExpr {
715            decl: this.clone(),
716            step: Some(def.clone()),
717            root: Some(def),
718            term: val,
719        })
720    }
721}
722
723impl Ord for Decl {
724    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
725        let base = match (self, other) {
726            (Self::Generated(l), Self::Generated(r)) => l.0.0.cmp(&r.0.0),
727            (Self::Module(l), Self::Module(r)) => l.fid.cmp(&r.fid),
728            (Self::Docs(l), Self::Docs(r)) => l.var.cmp(&r.var).then_with(|| l.base.cmp(&r.base)),
729            _ => self.span().into_raw().cmp(&other.span().into_raw()),
730        };
731
732        base.then_with(|| self.name().cmp(other.name()))
733    }
734}
735
736trait StrictCmp {
737    fn strict_cmp(&self, other: &Self) -> std::cmp::Ordering;
740}
741
742impl Decl {
743    pub fn strict_cmp(&self, other: &Self) -> std::cmp::Ordering {
745        let base = match (self, other) {
746            (Self::Generated(l), Self::Generated(r)) => l.0.0.cmp(&r.0.0),
747            (Self::Module(l), Self::Module(r)) => l.fid.strict_cmp(&r.fid),
748            (Self::Docs(l), Self::Docs(r)) => l
749                .var
750                .strict_cmp(&r.var)
751                .then_with(|| l.base.strict_cmp(&r.base)),
752            _ => self.span().strict_cmp(&other.span()),
753        };
754
755        base.then_with(|| self.name().cmp(other.name()))
756    }
757}
758
759impl StrictCmp for TypstFileId {
760    fn strict_cmp(&self, other: &Self) -> std::cmp::Ordering {
761        self.package()
762            .map(ToString::to_string)
763            .cmp(&other.package().map(ToString::to_string))
764            .then_with(|| self.vpath().cmp(other.vpath()))
765    }
766}
767impl<T: StrictCmp> StrictCmp for Option<T> {
768    fn strict_cmp(&self, other: &Self) -> std::cmp::Ordering {
769        match (self, other) {
770            (Some(l), Some(r)) => l.strict_cmp(r),
771            (Some(_), None) => std::cmp::Ordering::Greater,
772            (None, Some(_)) => std::cmp::Ordering::Less,
773            (None, None) => std::cmp::Ordering::Equal,
774        }
775    }
776}
777
778impl StrictCmp for Span {
779    fn strict_cmp(&self, other: &Self) -> std::cmp::Ordering {
780        self.id()
781            .strict_cmp(&other.id())
782            .then_with(|| self.into_raw().cmp(&other.into_raw()))
783    }
784}
785
786impl PartialOrd for Decl {
787    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
788        Some(self.cmp(other))
789    }
790}
791
792impl From<Decl> for Expr {
793    fn from(decl: Decl) -> Self {
794        Expr::Decl(decl.into())
795    }
796}
797
798impl From<DeclExpr> for Expr {
799    fn from(decl: DeclExpr) -> Self {
800        Expr::Decl(decl)
801    }
802}
803
804#[derive(Clone, PartialEq, Eq, Hash)]
806pub struct SpannedDecl {
807    name: Interned<str>,
809    at: Span,
811}
812
813impl SpannedDecl {
814    fn name(&self) -> &Interned<str> {
816        &self.name
817    }
818
819    fn span(&self) -> Span {
821        self.at
822    }
823}
824
825impl fmt::Debug for SpannedDecl {
826    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
827        f.write_str(self.name.as_ref())
828    }
829}
830
831#[derive(Clone, PartialEq, Eq, Hash)]
833pub struct NameRangeDecl {
834    pub name: Interned<str>,
836    pub at: Box<(TypstFileId, Range<usize>, Option<Range<usize>>)>,
838}
839
840impl NameRangeDecl {
841    fn name(&self) -> &Interned<str> {
843        &self.name
844    }
845
846    fn span(&self) -> Span {
848        Span::detached()
849    }
850}
851
852impl fmt::Debug for NameRangeDecl {
853    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
854        f.write_str(self.name.as_ref())
855    }
856}
857
858#[derive(Clone, PartialEq, Eq, Hash)]
860pub struct ModuleDecl {
861    pub name: Interned<str>,
863    pub fid: TypstFileId,
865}
866
867impl ModuleDecl {
868    fn name(&self) -> &Interned<str> {
870        &self.name
871    }
872
873    fn span(&self) -> Span {
875        Span::detached()
876    }
877}
878
879impl fmt::Debug for ModuleDecl {
880    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
881        f.write_str(self.name.as_ref())
882    }
883}
884
885#[derive(Clone, PartialEq, Eq, Hash)]
887pub struct DocsDecl {
888    base: Interned<Decl>,
889    var: Interned<TypeVar>,
890}
891
892impl DocsDecl {
893    fn name(&self) -> &Interned<str> {
895        Interned::empty()
896    }
897
898    fn span(&self) -> Span {
900        Span::detached()
901    }
902}
903
904impl fmt::Debug for DocsDecl {
905    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
906        write!(f, "{:?}, {:?}", self.base, self.var)
907    }
908}
909
910#[derive(Clone, PartialEq, Eq, Hash)]
912pub struct SpanDecl(Span);
913
914impl SpanDecl {
915    fn name(&self) -> &Interned<str> {
917        Interned::empty()
918    }
919
920    fn span(&self) -> Span {
922        self.0
923    }
924}
925
926impl fmt::Debug for SpanDecl {
927    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
928        write!(f, "..")
929    }
930}
931
932#[derive(Clone, PartialEq, Eq, Hash)]
934pub struct GeneratedDecl(DefId);
935
936impl GeneratedDecl {
937    fn name(&self) -> &Interned<str> {
939        Interned::empty()
940    }
941
942    fn span(&self) -> Span {
944        Span::detached()
945    }
946}
947
948impl fmt::Debug for GeneratedDecl {
949    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
950        self.0.fmt(f)
951    }
952}
953
954pub type UnExpr = UnInst<Expr>;
956pub type BinExpr = BinInst<Expr>;
958
959pub type ExportMap = BTreeMap<Interned<str>, Expr>;
963
964#[derive(Debug, Clone, PartialEq, Eq, Hash)]
968pub enum ArgExpr {
969    Pos(Expr),
971    Named(Box<(DeclExpr, Expr)>),
973    NamedRt(Box<(Expr, Expr)>),
975    Spread(Expr),
977}
978
979#[derive(Debug, Clone, PartialEq, Eq, Hash)]
981pub enum Pattern {
982    Expr(Expr),
985    Simple(Interned<Decl>),
987    Sig(Box<PatternSig>),
989}
990
991impl fmt::Display for Pattern {
992    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
993        ExprPrinter::new(f).write_pattern(self)
994    }
995}
996
997impl Pattern {
998    pub fn repr(&self) -> EcoString {
1000        let mut s = EcoString::new();
1001        let _ = ExprDescriber::new(&mut s).write_pattern(self);
1002        s
1003    }
1004}
1005
1006#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1011pub struct PatternSig {
1012    pub pos: EcoVec<Interned<Pattern>>,
1014    pub named: EcoVec<(DeclExpr, Interned<Pattern>)>,
1016    pub spread_left: Option<(DeclExpr, Interned<Pattern>)>,
1018    pub spread_right: Option<(DeclExpr, Interned<Pattern>)>,
1020}
1021
1022impl Pattern {}
1023
1024impl_internable!(Decl,);
1025
1026#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1030pub struct ContentSeqExpr {
1031    pub ty: Ty,
1033}
1034
1035#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1080pub struct RefExpr {
1081    pub decl: DeclExpr,
1086
1087    pub step: Option<Expr>,
1097
1098    pub root: Option<Expr>,
1102
1103    pub term: Option<Ty>,
1111}
1112
1113#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1115pub struct ContentRefExpr {
1116    pub ident: DeclExpr,
1118    pub of: Option<DeclExpr>,
1120    pub body: Option<Expr>,
1122}
1123
1124#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1126pub struct SelectExpr {
1127    pub lhs: Expr,
1129    pub key: DeclExpr,
1131    pub span: Span,
1133}
1134
1135impl SelectExpr {
1136    pub fn new(key: DeclExpr, lhs: Expr) -> Interned<Self> {
1138        Interned::new(Self {
1139            key,
1140            lhs,
1141            span: Span::detached(),
1142        })
1143    }
1144}
1145
1146#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1148pub struct ArgsExpr {
1149    pub args: Vec<ArgExpr>,
1151    pub span: Span,
1153}
1154
1155impl ArgsExpr {
1156    pub fn new(span: Span, args: Vec<ArgExpr>) -> Interned<Self> {
1158        Interned::new(Self { args, span })
1159    }
1160}
1161
1162#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1164pub struct ElementExpr {
1165    pub elem: Element,
1167    pub content: EcoVec<Expr>,
1169}
1170
1171#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1173pub struct ApplyExpr {
1174    pub callee: Expr,
1176    pub args: Expr,
1178    pub span: Span,
1180}
1181
1182#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1184pub struct FuncExpr {
1185    pub decl: DeclExpr,
1187    pub params: PatternSig,
1189    pub body: Expr,
1191}
1192
1193#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1195pub struct LetExpr {
1196    pub span: Span,
1198    pub pattern: Interned<Pattern>,
1200    pub body: Option<Expr>,
1202}
1203
1204#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1206pub struct ShowExpr {
1207    pub selector: Option<Expr>,
1209    pub edit: Expr,
1211}
1212
1213#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1215pub struct SetExpr {
1216    pub target: Expr,
1218    pub args: Expr,
1220    pub cond: Option<Expr>,
1222}
1223
1224#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1226pub struct ImportExpr {
1227    pub decl: Interned<RefExpr>,
1229}
1230
1231#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1233pub struct IncludeExpr {
1234    pub source: Expr,
1236}
1237
1238#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1240pub struct IfExpr {
1241    pub cond: Expr,
1243    pub then: Expr,
1245    pub else_: Expr,
1247}
1248
1249#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1251pub struct WhileExpr {
1252    pub cond: Expr,
1254    pub body: Expr,
1256}
1257
1258#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1260pub struct ForExpr {
1261    pub pattern: Interned<Pattern>,
1263    pub iter: Expr,
1265    pub body: Expr,
1267}
1268
1269#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
1271pub enum UnaryOp {
1272    Pos,
1275    Neg,
1278    Not,
1281    Return,
1284    Context,
1287    Spread,
1290    NotElementOf,
1293    ElementOf,
1296    TypeOf,
1299}
1300
1301#[derive(Debug, Hash, Clone, PartialEq, Eq)]
1303pub struct UnInst<T> {
1304    pub lhs: T,
1306    pub op: UnaryOp,
1308}
1309
1310impl<T: Ord> PartialOrd for UnInst<T> {
1311    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1312        Some(self.cmp(other))
1313    }
1314}
1315
1316impl<T: Ord> Ord for UnInst<T> {
1317    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1318        let op_as_int = self.op as u8;
1319        let other_op_as_int = other.op as u8;
1320        op_as_int
1321            .cmp(&other_op_as_int)
1322            .then_with(|| self.lhs.cmp(&other.lhs))
1323    }
1324}
1325
1326impl UnInst<Expr> {
1327    pub fn new(op: UnaryOp, lhs: Expr) -> Interned<Self> {
1329        Interned::new(Self { lhs, op })
1330    }
1331}
1332
1333impl<T> UnInst<T> {
1334    pub fn operands(&self) -> [&T; 1] {
1336        [&self.lhs]
1337    }
1338}
1339
1340pub type BinaryOp = ast::BinOp;
1342
1343#[derive(Debug, Hash, Clone, PartialEq, Eq)]
1345pub struct BinInst<T> {
1346    pub operands: (T, T),
1348    pub op: BinaryOp,
1350}
1351
1352impl<T: Ord> PartialOrd for BinInst<T> {
1353    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1354        Some(self.cmp(other))
1355    }
1356}
1357
1358impl<T: Ord> Ord for BinInst<T> {
1359    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1360        let op_as_int = self.op as u8;
1361        let other_op_as_int = other.op as u8;
1362        op_as_int
1363            .cmp(&other_op_as_int)
1364            .then_with(|| self.operands.cmp(&other.operands))
1365    }
1366}
1367
1368impl BinInst<Expr> {
1369    pub fn new(op: BinaryOp, lhs: Expr, rhs: Expr) -> Interned<Self> {
1371        Interned::new(Self {
1372            operands: (lhs, rhs),
1373            op,
1374        })
1375    }
1376}
1377
1378impl<T> BinInst<T> {
1379    pub fn operands(&self) -> [&T; 2] {
1381        [&self.operands.0, &self.operands.1]
1382    }
1383}
1384
1385fn is_empty_scope(scope: &typst::foundations::Scope) -> bool {
1387    scope.iter().next().is_none()
1388}
1389
1390impl_internable!(
1391    Expr,
1392    ArgsExpr,
1393    ElementExpr,
1394    ContentSeqExpr,
1395    RefExpr,
1396    ContentRefExpr,
1397    SelectExpr,
1398    ImportExpr,
1399    IncludeExpr,
1400    IfExpr,
1401    WhileExpr,
1402    ForExpr,
1403    FuncExpr,
1404    LetExpr,
1405    ShowExpr,
1406    SetExpr,
1407    Pattern,
1408    EcoVec<(Decl, Expr)>,
1409    Vec<ArgExpr>,
1410    Vec<Expr>,
1411    UnInst<Expr>,
1412    BinInst<Expr>,
1413    ApplyExpr,
1414);