Skip to main content

cl_ast/ast/
types.rs

1//! The default (as-parsed) implementation of the AST's customization points.
2
3use std::fmt::Display;
4
5use crate::{ast::AstTypes, fmt::FmtAdapter};
6
7use cl_structures::{intern::interned::Interned, span::Span};
8
9/// The types emitted by the parser
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
11pub struct DefaultTypes;
12
13impl AstTypes for DefaultTypes {
14    type Annotation = Span;
15    type Literal = Literal;
16    type MacroId = Symbol;
17    type Symbol = Symbol;
18    type Path = Path;
19}
20
21impl std::fmt::Display for DefaultTypes {
22    fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        Ok(())
24    }
25}
26
27/// An interned symbol (i.e. a name)
28pub type Symbol = Interned<'static, str>;
29
30/// A qualified identifier
31///
32/// TODO: qualify identifier
33#[derive(Clone, Debug, PartialEq, Eq, Hash)]
34pub struct Path {
35    // TODO: Identifier interning
36    pub parts: Vec<Symbol>,
37    // TODO: generic parameters
38}
39
40impl Path {
41    /// Returns the "root path": `::`
42    pub fn root() -> Path {
43        Path { parts: vec!["".into()] }
44    }
45    /// Returns the last path segment
46    pub fn name(&self) -> Option<Symbol> {
47        match self.parts.as_slice() {
48            [] => None,
49            [.., name] => Some(*name),
50        }
51    }
52}
53
54impl From<&str> for Path {
55    fn from(value: &str) -> Self {
56        Self { parts: vec![value.into()] }
57    }
58}
59
60impl From<Symbol> for Path {
61    fn from(value: Symbol) -> Self {
62        Self { parts: vec![value] }
63    }
64}
65
66impl std::fmt::Display for Path {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        let Self { parts } = self;
69        match parts.as_slice() {
70            [Interned("", ..)] => f.write_str("::"),
71            parts => f.list(parts, "::"),
72        }
73    }
74}
75
76/// A literal value (boolean, character, integer, string)
77#[derive(Clone, Debug, PartialEq, Eq, Hash)]
78pub enum Literal {
79    /// A boolean literal: true | false
80    Bool(bool),
81    /// A character literal: 'a', '\u{1f988}'
82    Char(char),
83    /// An integer literal: 0, 123, 0x10
84    Int(u128, u32),
85    /// A string literal:
86    Str(String),
87}
88
89impl Display for Literal {
90    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91        match self {
92            Self::Bool(v) => v.fmt(f),
93            Self::Char(c) => write!(f, "'{}'", c.escape_debug()),
94            Self::Int(i, 2) => write!(f, "0b{i:b}"),
95            Self::Int(i, 8) => write!(f, "0o{i:o}"),
96            Self::Int(i, 16) => write!(f, "0x{i:x}"),
97            Self::Int(i, _) => i.fmt(f),
98            Self::Str(s) => write!(f, "\"{}\"", s.escape_debug()),
99        }
100    }
101}