cl_ast/
ast.rs

1//! # The Abstract Syntax Tree
2//! Contains definitions of Conlang AST Nodes.
3//!
4//! # Notable nodes
5//! - [Item] and [ItemKind]: Top-level constructs
6//! - [Stmt] and [StmtKind]: Statements
7//! - [Expr] and [ExprKind]: Expressions
8//!   - [Assign], [Modify], [Binary], and [Unary] expressions
9//!   - [ModifyKind], [BinaryKind], and [UnaryKind] operators
10//! - [Ty] and [TyKind]: Type qualifiers
11//! - [Pattern]: Pattern matching operators
12//! - [Path]: Path expressions
13use cl_structures::{intern::interned::Interned, span::*};
14
15/// An [Interned] static [str], used in place of an identifier
16pub type Sym = Interned<'static, str>;
17
18/// Whether a binding ([Static] or [Let]) or reference is mutable or not
19#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
20pub enum Mutability {
21    #[default]
22    Not,
23    Mut,
24}
25
26/// Whether an [Item] is visible outside of the current [Module]
27#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
28pub enum Visibility {
29    #[default]
30    Private,
31    Public,
32}
33
34/// A list of [Item]s
35#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
36pub struct File {
37    pub name: &'static str,
38    pub items: Vec<Item>,
39}
40
41/// A list of [Meta] decorators
42#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
43pub struct Attrs {
44    pub meta: Vec<Meta>,
45}
46
47/// A metadata decorator
48#[derive(Clone, Debug, PartialEq, Eq, Hash)]
49pub struct Meta {
50    pub name: Sym,
51    pub kind: MetaKind,
52}
53
54/// Information attached to [Meta]data
55#[derive(Clone, Debug, PartialEq, Eq, Hash)]
56pub enum MetaKind {
57    Plain,
58    Equals(Literal),
59    Func(Vec<Literal>),
60}
61
62// Items
63/// Anything that can appear at the top level of a [File]
64#[derive(Clone, Debug, PartialEq, Eq, Hash)]
65pub struct Item {
66    pub span: Span,
67    pub attrs: Attrs,
68    pub vis: Visibility,
69    pub kind: ItemKind,
70}
71
72/// What kind of [Item] is this?
73#[derive(Clone, Debug, PartialEq, Eq, Hash)]
74pub enum ItemKind {
75    // TODO: Trait declaration ("trait") item?
76    /// A [module](Module)
77    Module(Module),
78    /// A [type alias](Alias)
79    Alias(Alias),
80    /// An [enumerated type](Enum), with a discriminant and optional data
81    Enum(Enum),
82    /// A [structure](Struct)
83    Struct(Struct),
84    /// A [constant](Const)
85    Const(Const),
86    /// A [static](Static) variable
87    Static(Static),
88    /// A [function definition](Function)
89    Function(Function),
90    /// An [implementation](Impl)
91    Impl(Impl),
92    /// An [import](Use)
93    Use(Use),
94}
95
96/// A list of type variables to introduce
97#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
98pub struct Generics {
99    pub vars: Vec<Sym>,
100}
101
102/// An ordered collection of [Items](Item)
103#[derive(Clone, Debug, PartialEq, Eq, Hash)]
104pub struct Module {
105    pub name: Sym,
106    pub file: Option<File>,
107}
108
109/// An alias to another [Ty]
110#[derive(Clone, Debug, PartialEq, Eq, Hash)]
111pub struct Alias {
112    pub name: Sym,
113    pub from: Option<Box<Ty>>,
114}
115
116/// A compile-time constant
117#[derive(Clone, Debug, PartialEq, Eq, Hash)]
118pub struct Const {
119    pub name: Sym,
120    pub ty: Box<Ty>,
121    pub init: Box<Expr>,
122}
123
124/// A `static` variable
125#[derive(Clone, Debug, PartialEq, Eq, Hash)]
126pub struct Static {
127    pub mutable: Mutability,
128    pub name: Sym,
129    pub ty: Box<Ty>,
130    pub init: Box<Expr>,
131}
132
133/// Code, and the interface to that code
134#[derive(Clone, Debug, PartialEq, Eq, Hash)]
135pub struct Function {
136    pub name: Sym,
137    pub gens: Generics,
138    pub sign: TyFn,
139    pub bind: Pattern,
140    pub body: Option<Expr>,
141}
142
143/// A user-defined product type
144#[derive(Clone, Debug, PartialEq, Eq, Hash)]
145pub struct Struct {
146    pub name: Sym,
147    pub gens: Generics,
148    pub kind: StructKind,
149}
150
151/// Either a [Struct]'s [StructMember]s or tuple [Ty]pes, if present.
152#[derive(Clone, Debug, PartialEq, Eq, Hash)]
153pub enum StructKind {
154    Empty,
155    Tuple(Vec<Ty>),
156    Struct(Vec<StructMember>),
157}
158
159/// The [Visibility], [Sym], and [Ty]pe of a single [Struct] member
160#[derive(Clone, Debug, PartialEq, Eq, Hash)]
161pub struct StructMember {
162    pub vis: Visibility,
163    pub name: Sym,
164    pub ty: Ty,
165}
166
167/// A user-defined sum type
168#[derive(Clone, Debug, PartialEq, Eq, Hash)]
169pub struct Enum {
170    pub name: Sym,
171    pub gens: Generics,
172    pub variants: Vec<Variant>,
173}
174
175/// A single [Enum] variant
176#[derive(Clone, Debug, PartialEq, Eq, Hash)]
177pub struct Variant {
178    pub name: Sym,
179    pub kind: StructKind,
180    pub body: Option<Box<Expr>>,
181}
182
183/// Sub-[items](Item) (associated functions, etc.) for a [Ty]
184#[derive(Clone, Debug, PartialEq, Eq, Hash)]
185pub struct Impl {
186    pub gens: Generics,
187    pub target: ImplKind,
188    pub body: File,
189}
190
191// TODO: `impl` Trait for <Target> { }
192#[derive(Clone, Debug, PartialEq, Eq, Hash)]
193pub enum ImplKind {
194    Type(Ty),
195    Trait { impl_trait: Path, for_type: Box<Ty> },
196}
197
198/// An import of nonlocal [Item]s
199#[derive(Clone, Debug, PartialEq, Eq, Hash)]
200pub struct Use {
201    pub absolute: bool,
202    pub tree: UseTree,
203}
204
205/// A tree of [Item] imports
206#[derive(Clone, Debug, PartialEq, Eq, Hash)]
207pub enum UseTree {
208    Tree(Vec<UseTree>),
209    Path(PathPart, Box<UseTree>),
210    Alias(Sym, Sym),
211    Name(Sym),
212    Glob,
213}
214
215/// A type expression
216#[derive(Clone, Debug, PartialEq, Eq, Hash)]
217pub struct Ty {
218    pub span: Span,
219    pub kind: TyKind,
220    pub gens: Generics,
221}
222
223/// Information about a [Ty]pe expression
224#[derive(Clone, Debug, PartialEq, Eq, Hash)]
225pub enum TyKind {
226    Never,
227    Infer,
228    Path(Path),
229    Array(TyArray),
230    Slice(TySlice),
231    Tuple(TyTuple),
232    Ref(TyRef),
233    Ptr(TyPtr),
234    Fn(TyFn),
235}
236
237/// An array of [`T`](Ty)
238#[derive(Clone, Debug, PartialEq, Eq, Hash)]
239pub struct TyArray {
240    pub ty: Box<Ty>,
241    pub count: usize,
242}
243
244/// A [Ty]pe slice expression: `[T]`
245#[derive(Clone, Debug, PartialEq, Eq, Hash)]
246pub struct TySlice {
247    pub ty: Box<Ty>,
248}
249
250/// A tuple of [Ty]pes
251#[derive(Clone, Debug, PartialEq, Eq, Hash)]
252pub struct TyTuple {
253    pub types: Vec<Ty>,
254}
255
256/// A [Ty]pe-reference expression as (number of `&`, [Path])
257#[derive(Clone, Debug, PartialEq, Eq, Hash)]
258pub struct TyRef {
259    pub mutable: Mutability,
260    pub count: u16,
261    pub to: Box<Ty>,
262}
263
264/// A [Ty]pe-reference expression as (number of `&`, [Path])
265#[derive(Clone, Debug, PartialEq, Eq, Hash)]
266pub struct TyPtr {
267    pub to: Box<Ty>,
268}
269
270/// The args and return value for a function pointer [Ty]pe
271#[derive(Clone, Debug, PartialEq, Eq, Hash)]
272pub struct TyFn {
273    pub args: Box<Ty>,
274    pub rety: Box<Ty>,
275}
276
277/// A path to an [Item] in the [Module] tree
278#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
279pub struct Path {
280    pub absolute: bool,
281    pub parts: Vec<PathPart>,
282}
283
284/// A single component of a [Path]
285#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
286pub enum PathPart {
287    SuperKw,
288    SelfTy,
289    Ident(Sym),
290}
291
292/// An abstract statement, and associated metadata
293#[derive(Clone, Debug, PartialEq, Eq, Hash)]
294pub struct Stmt {
295    pub span: Span,
296    pub kind: StmtKind,
297    pub semi: Semi,
298}
299
300/// Whether the [Stmt] is a [Let], [Item], or [Expr] statement
301#[derive(Clone, Debug, PartialEq, Eq, Hash)]
302pub enum StmtKind {
303    Empty,
304    Item(Box<Item>),
305    Expr(Box<Expr>),
306}
307
308/// Whether or not a [Stmt] is followed by a semicolon
309#[derive(Clone, Debug, PartialEq, Eq, Hash)]
310pub enum Semi {
311    Terminated,
312    Unterminated,
313}
314
315/// An expression, the beating heart of the language
316#[derive(Clone, Debug, PartialEq, Eq, Hash)]
317pub struct Expr {
318    pub span: Span,
319    pub kind: ExprKind,
320}
321
322/// Any of the different [Expr]essions
323#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
324pub enum ExprKind {
325    /// An empty expression: `(` `)`
326    #[default]
327    Empty,
328    /// A [Closure] expression: `|` [`Expr`] `|` ( -> [`Ty`])? [`Expr`]
329    Closure(Closure),
330    /// A [Tuple] expression: `(` [`Expr`] (`,` [`Expr`])+ `)`
331    Tuple(Tuple),
332    /// A [Struct creation](Structor) expression: [Path] `{` ([Fielder] `,`)* [Fielder]? `}`
333    Structor(Structor),
334    /// An [Array] literal: `[` [`Expr`] (`,` [`Expr`])\* `]`
335    Array(Array),
336    /// An Array literal constructed with [repeat syntax](ArrayRep)
337    /// `[` [Expr] `;` [Literal] `]`
338    ArrayRep(ArrayRep),
339    /// An address-of expression: `&` `mut`? [`Expr`]
340    AddrOf(AddrOf),
341    /// A backtick-quoted expression
342    Quote(Quote),
343    /// A [Literal]: 0x42, 1e123, 2.4, "Hello"
344    Literal(Literal),
345    /// A [Grouping](Group) expression `(` [`Expr`] `)`
346    Group(Group),
347    /// A [Block] expression: `{` [`Stmt`]\* [`Expr`]? `}`
348    Block(Block),
349
350    /// An [Assign]ment expression: [`Expr`] (`=` [`Expr`])\+
351    Assign(Assign),
352    /// A [Modify]-assignment expression: [`Expr`] ([`ModifyKind`] [`Expr`])\+
353    Modify(Modify),
354    /// A [Binary] expression: [`Expr`] ([`BinaryKind`] [`Expr`])\+
355    Binary(Binary),
356    /// A [Unary] expression: [`UnaryKind`]\* [`Expr`]
357    Unary(Unary),
358    /// A [Member] access expression: [`Expr`] [`MemberKind`]\*
359    Member(Member),
360    /// An Array [Index] expression: a[10, 20, 30]
361    Index(Index),
362    /// A [Cast] expression: [`Expr`] `as` [`Ty`]
363    Cast(Cast),
364    /// A [path expression](Path): `::`? [PathPart] (`::` [PathPart])*
365    Path(Path),
366    /// A local bind instruction, `let` [`Sym`] `=` [`Expr`]
367    Let(Let),
368    /// A [Match] expression: `match` [Expr] `{` ([MatchArm] `,`)* [MatchArm]? `}`
369    Match(Match),
370    /// A [While] expression: `while` [`Expr`] [`Block`] [`Else`]?
371    While(While),
372    /// An [If] expression: `if` [`Expr`] [`Block`] [`Else`]?
373    If(If),
374    /// A [For] expression: `for` [`Pattern`] `in` [`Expr`] [`Block`] [`Else`]?
375    For(For),
376    /// A [Break] expression: `break` [`Expr`]?
377    Break(Break),
378    /// A [Return] expression `return` [`Expr`]?
379    Return(Return),
380    /// A continue expression: `continue`
381    Continue,
382}
383
384/// A Closure [expression](Expr): `|` [`Expr`] `|` ( -> [`Ty`])? [`Expr`]
385#[derive(Clone, Debug, PartialEq, Eq, Hash)]
386pub struct Closure {
387    pub arg: Box<Pattern>,
388    pub body: Box<Expr>,
389}
390
391/// A [Tuple] expression: `(` [`Expr`] (`,` [`Expr`])+ `)`
392#[derive(Clone, Debug, PartialEq, Eq, Hash)]
393pub struct Tuple {
394    pub exprs: Vec<Expr>,
395}
396
397/// A [Struct creation](Structor) expression: [Path] `{` ([Fielder] `,`)* [Fielder]? `}`
398#[derive(Clone, Debug, PartialEq, Eq, Hash)]
399pub struct Structor {
400    pub to: Path,
401    pub init: Vec<Fielder>,
402}
403
404/// A [Struct field initializer] expression: [Sym] (`=` [Expr])?
405#[derive(Clone, Debug, PartialEq, Eq, Hash)]
406pub struct Fielder {
407    pub name: Sym,
408    pub init: Option<Box<Expr>>,
409}
410
411/// An [Array] literal: `[` [`Expr`] (`,` [`Expr`])\* `]`
412#[derive(Clone, Debug, PartialEq, Eq, Hash)]
413pub struct Array {
414    pub values: Vec<Expr>,
415}
416
417/// An Array literal constructed with [repeat syntax](ArrayRep)
418/// `[` [Expr] `;` [Literal] `]`
419#[derive(Clone, Debug, PartialEq, Eq, Hash)]
420pub struct ArrayRep {
421    pub value: Box<Expr>,
422    pub repeat: Box<Expr>,
423}
424
425/// An address-of expression: `&` `mut`? [`Expr`]
426#[derive(Clone, Debug, PartialEq, Eq, Hash)]
427pub struct AddrOf {
428    pub mutable: Mutability,
429    pub expr: Box<Expr>,
430}
431
432/// A cast expression: [`Expr`] `as` [`Ty`]
433#[derive(Clone, Debug, PartialEq, Eq, Hash)]
434pub struct Cast {
435    pub head: Box<Expr>,
436    pub ty: Ty,
437}
438
439/// A backtick-quoted subexpression-literal
440#[derive(Clone, Debug, PartialEq, Eq, Hash)]
441pub struct Quote {
442    pub quote: Box<Expr>,
443}
444
445/// A [Literal]: 0x42, 1e123, 2.4, "Hello"
446#[derive(Clone, Debug, PartialEq, Eq, Hash)]
447pub enum Literal {
448    Bool(bool),
449    Char(char),
450    Int(u128),
451    Float(u64),
452    String(String),
453}
454
455/// A [Grouping](Group) expression `(` [`Expr`] `)`
456#[derive(Clone, Debug, PartialEq, Eq, Hash)]
457pub struct Group {
458    pub expr: Box<Expr>,
459}
460
461/// A [Block] expression: `{` [`Stmt`]\* [`Expr`]? `}`
462#[derive(Clone, Debug, PartialEq, Eq, Hash)]
463pub struct Block {
464    pub stmts: Vec<Stmt>,
465}
466
467/// An [Assign]ment expression: [`Expr`] ([`ModifyKind`] [`Expr`])\+
468#[derive(Clone, Debug, PartialEq, Eq, Hash)]
469pub struct Assign {
470    pub parts: Box<(Expr, Expr)>,
471}
472
473/// A [Modify]-assignment expression: [`Expr`] ([`ModifyKind`] [`Expr`])\+
474#[derive(Clone, Debug, PartialEq, Eq, Hash)]
475pub struct Modify {
476    pub kind: ModifyKind,
477    pub parts: Box<(Expr, Expr)>,
478}
479
480#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
481pub enum ModifyKind {
482    And,
483    Or,
484    Xor,
485    Shl,
486    Shr,
487    Add,
488    Sub,
489    Mul,
490    Div,
491    Rem,
492}
493
494/// A [Binary] expression: [`Expr`] ([`BinaryKind`] [`Expr`])\+
495#[derive(Clone, Debug, PartialEq, Eq, Hash)]
496pub struct Binary {
497    pub kind: BinaryKind,
498    pub parts: Box<(Expr, Expr)>,
499}
500
501/// A [Binary] operator
502#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
503pub enum BinaryKind {
504    Lt,
505    LtEq,
506    Equal,
507    NotEq,
508    GtEq,
509    Gt,
510    RangeExc,
511    RangeInc,
512    LogAnd,
513    LogOr,
514    LogXor,
515    BitAnd,
516    BitOr,
517    BitXor,
518    Shl,
519    Shr,
520    Add,
521    Sub,
522    Mul,
523    Div,
524    Rem,
525    Call,
526}
527
528/// A [Unary] expression: [`UnaryKind`]\* [`Expr`]
529#[derive(Clone, Debug, PartialEq, Eq, Hash)]
530pub struct Unary {
531    pub kind: UnaryKind,
532    pub tail: Box<Expr>,
533}
534
535/// A [Unary] operator
536#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
537pub enum UnaryKind {
538    Deref,
539    Neg,
540    Not,
541    RangeInc,
542    RangeExc,
543    /// A Loop expression: `loop` [`Block`]
544    Loop,
545    /// Unused
546    At,
547    /// Unused
548    Tilde,
549}
550
551/// A [Member] access expression: [`Expr`] [`MemberKind`]\*
552#[derive(Clone, Debug, PartialEq, Eq, Hash)]
553pub struct Member {
554    pub head: Box<Expr>,
555    pub kind: MemberKind,
556}
557
558/// The kind of [Member] access
559#[derive(Clone, Debug, PartialEq, Eq, Hash)]
560pub enum MemberKind {
561    Call(Sym, Tuple),
562    Struct(Sym),
563    Tuple(Literal),
564}
565
566/// A repeated [Index] expression: a[10, 20, 30][40, 50, 60]
567#[derive(Clone, Debug, PartialEq, Eq, Hash)]
568pub struct Index {
569    pub head: Box<Expr>,
570    pub indices: Vec<Expr>,
571}
572
573/// A local variable declaration [Stmt]
574#[derive(Clone, Debug, PartialEq, Eq, Hash)]
575pub struct Let {
576    pub mutable: Mutability,
577    pub name: Pattern,
578    pub ty: Option<Box<Ty>>,
579    pub init: Option<Box<Expr>>,
580}
581
582/// A `match` expression: `match` `{` ([MatchArm] `,`)* [MatchArm]? `}`
583#[derive(Clone, Debug, PartialEq, Eq, Hash)]
584pub struct Match {
585    pub scrutinee: Box<Expr>,
586    pub arms: Vec<MatchArm>,
587}
588
589/// A single arm of a [Match] expression: [`Pattern`] `=>` [`Expr`]
590#[derive(Clone, Debug, PartialEq, Eq, Hash)]
591pub struct MatchArm(pub Pattern, pub Expr);
592
593/// A [Pattern] meta-expression (any [`ExprKind`] that fits pattern rules)
594#[derive(Clone, Debug, PartialEq, Eq, Hash)]
595pub enum Pattern {
596    Name(Sym),
597    Path(Path),
598    Literal(Literal),
599    Rest(Option<Box<Pattern>>),
600    Ref(Mutability, Box<Pattern>),
601    RangeExc(Box<Pattern>, Box<Pattern>),
602    RangeInc(Box<Pattern>, Box<Pattern>),
603    Tuple(Vec<Pattern>),
604    Array(Vec<Pattern>),
605    Struct(Path, Vec<(Sym, Option<Pattern>)>),
606    TupleStruct(Path, Vec<Pattern>),
607}
608
609/// A [While] expression: `while` [`Expr`] [`Block`] [`Else`]?
610#[derive(Clone, Debug, PartialEq, Eq, Hash)]
611pub struct While {
612    pub cond: Box<Expr>,
613    pub pass: Box<Block>,
614    pub fail: Else,
615}
616
617/// An [If] expression: `if` [`Expr`] [`Block`] [`Else`]?
618#[derive(Clone, Debug, PartialEq, Eq, Hash)]
619pub struct If {
620    pub cond: Box<Expr>,
621    pub pass: Box<Block>,
622    pub fail: Else,
623}
624
625/// A [For] expression: `for` Pattern `in` [`Expr`] [`Block`] [`Else`]?
626#[derive(Clone, Debug, PartialEq, Eq, Hash)]
627pub struct For {
628    pub bind: Pattern,
629    pub cond: Box<Expr>,
630    pub pass: Box<Block>,
631    pub fail: Else,
632}
633
634/// The (optional) `else` clause of a [While], [If], or [For] expression
635#[derive(Clone, Debug, PartialEq, Eq, Hash)]
636pub struct Else {
637    pub body: Option<Box<Expr>>,
638}
639
640/// A [Break] expression: `break` [`Expr`]?
641#[derive(Clone, Debug, PartialEq, Eq, Hash)]
642pub struct Break {
643    pub body: Option<Box<Expr>>,
644}
645
646/// A [Return] expression `return` [`Expr`]?
647#[derive(Clone, Debug, PartialEq, Eq, Hash)]
648pub struct Return {
649    pub body: Option<Box<Expr>>,
650}