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 target: ImplKind,
187    pub body: File,
188}
189
190// TODO: `impl` Trait for <Target> { }
191#[derive(Clone, Debug, PartialEq, Eq, Hash)]
192pub enum ImplKind {
193    Type(Ty),
194    Trait { impl_trait: Path, for_type: Box<Ty> },
195}
196
197/// An import of nonlocal [Item]s
198#[derive(Clone, Debug, PartialEq, Eq, Hash)]
199pub struct Use {
200    pub absolute: bool,
201    pub tree: UseTree,
202}
203
204/// A tree of [Item] imports
205#[derive(Clone, Debug, PartialEq, Eq, Hash)]
206pub enum UseTree {
207    Tree(Vec<UseTree>),
208    Path(PathPart, Box<UseTree>),
209    Alias(Sym, Sym),
210    Name(Sym),
211    Glob,
212}
213
214/// A type expression
215#[derive(Clone, Debug, PartialEq, Eq, Hash)]
216pub struct Ty {
217    pub span: Span,
218    pub kind: TyKind,
219}
220
221/// Information about a [Ty]pe expression
222#[derive(Clone, Debug, PartialEq, Eq, Hash)]
223pub enum TyKind {
224    Never,
225    Empty,
226    Infer,
227    Path(Path),
228    Array(TyArray),
229    Slice(TySlice),
230    Tuple(TyTuple),
231    Ref(TyRef),
232    Fn(TyFn),
233}
234
235/// An array of [`T`](Ty)
236#[derive(Clone, Debug, PartialEq, Eq, Hash)]
237pub struct TyArray {
238    pub ty: Box<TyKind>,
239    pub count: usize,
240}
241
242/// A [Ty]pe slice expression: `[T]`
243#[derive(Clone, Debug, PartialEq, Eq, Hash)]
244pub struct TySlice {
245    pub ty: Box<TyKind>,
246}
247
248/// A tuple of [Ty]pes
249#[derive(Clone, Debug, PartialEq, Eq, Hash)]
250pub struct TyTuple {
251    pub types: Vec<TyKind>,
252}
253
254/// A [Ty]pe-reference expression as (number of `&`, [Path])
255#[derive(Clone, Debug, PartialEq, Eq, Hash)]
256pub struct TyRef {
257    pub mutable: Mutability,
258    pub count: u16,
259    pub to: Box<Ty>,
260}
261
262/// The args and return value for a function pointer [Ty]pe
263#[derive(Clone, Debug, PartialEq, Eq, Hash)]
264pub struct TyFn {
265    pub args: Box<TyKind>,
266    pub rety: Option<Box<Ty>>,
267}
268
269/// A path to an [Item] in the [Module] tree
270#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
271pub struct Path {
272    pub absolute: bool,
273    pub parts: Vec<PathPart>,
274}
275
276/// A single component of a [Path]
277#[derive(Clone, Debug, PartialEq, Eq, Hash)]
278pub enum PathPart {
279    SuperKw,
280    SelfTy,
281    Ident(Sym),
282}
283
284/// An abstract statement, and associated metadata
285#[derive(Clone, Debug, PartialEq, Eq, Hash)]
286pub struct Stmt {
287    pub span: Span,
288    pub kind: StmtKind,
289    pub semi: Semi,
290}
291
292/// Whether the [Stmt] is a [Let], [Item], or [Expr] statement
293#[derive(Clone, Debug, PartialEq, Eq, Hash)]
294pub enum StmtKind {
295    Empty,
296    Item(Box<Item>),
297    Expr(Box<Expr>),
298}
299
300/// Whether or not a [Stmt] is followed by a semicolon
301#[derive(Clone, Debug, PartialEq, Eq, Hash)]
302pub enum Semi {
303    Terminated,
304    Unterminated,
305}
306
307/// An expression, the beating heart of the language
308#[derive(Clone, Debug, PartialEq, Eq, Hash)]
309pub struct Expr {
310    pub span: Span,
311    pub kind: ExprKind,
312}
313
314/// Any of the different [Expr]essions
315#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
316pub enum ExprKind {
317    /// An empty expression: `(` `)`
318    #[default]
319    Empty,
320    /// A [Closure] expression: `|` [`Expr`] `|` ( -> [`Ty`])? [`Expr`]
321    Closure(Closure),
322    /// A [Tuple] expression: `(` [`Expr`] (`,` [`Expr`])+ `)`
323    Tuple(Tuple),
324    /// A [Struct creation](Structor) expression: [Path] `{` ([Fielder] `,`)* [Fielder]? `}`
325    Structor(Structor),
326    /// An [Array] literal: `[` [`Expr`] (`,` [`Expr`])\* `]`
327    Array(Array),
328    /// An Array literal constructed with [repeat syntax](ArrayRep)
329    /// `[` [Expr] `;` [Literal] `]`
330    ArrayRep(ArrayRep),
331    /// An address-of expression: `&` `mut`? [`Expr`]
332    AddrOf(AddrOf),
333    /// A backtick-quoted expression
334    Quote(Quote),
335    /// A [Literal]: 0x42, 1e123, 2.4, "Hello"
336    Literal(Literal),
337    /// A [Grouping](Group) expression `(` [`Expr`] `)`
338    Group(Group),
339    /// A [Block] expression: `{` [`Stmt`]\* [`Expr`]? `}`
340    Block(Block),
341
342    /// An [Assign]ment expression: [`Expr`] (`=` [`Expr`])\+
343    Assign(Assign),
344    /// A [Modify]-assignment expression: [`Expr`] ([`ModifyKind`] [`Expr`])\+
345    Modify(Modify),
346    /// A [Binary] expression: [`Expr`] ([`BinaryKind`] [`Expr`])\+
347    Binary(Binary),
348    /// A [Unary] expression: [`UnaryKind`]\* [`Expr`]
349    Unary(Unary),
350    /// A [Member] access expression: [`Expr`] [`MemberKind`]\*
351    Member(Member),
352    /// An Array [Index] expression: a[10, 20, 30]
353    Index(Index),
354    /// A [Cast] expression: [`Expr`] `as` [`Ty`]
355    Cast(Cast),
356    /// A [path expression](Path): `::`? [PathPart] (`::` [PathPart])*
357    Path(Path),
358    /// A local bind instruction, `let` [`Sym`] `=` [`Expr`]
359    Let(Let),
360    /// A [Match] expression: `match` [Expr] `{` ([MatchArm] `,`)* [MatchArm]? `}`
361    Match(Match),
362    /// A [While] expression: `while` [`Expr`] [`Block`] [`Else`]?
363    While(While),
364    /// An [If] expression: `if` [`Expr`] [`Block`] [`Else`]?
365    If(If),
366    /// A [For] expression: `for` [`Pattern`] `in` [`Expr`] [`Block`] [`Else`]?
367    For(For),
368    /// A [Break] expression: `break` [`Expr`]?
369    Break(Break),
370    /// A [Return] expression `return` [`Expr`]?
371    Return(Return),
372    /// A continue expression: `continue`
373    Continue,
374}
375
376/// A Closure [expression](Expr): `|` [`Expr`] `|` ( -> [`Ty`])? [`Expr`]
377#[derive(Clone, Debug, PartialEq, Eq, Hash)]
378pub struct Closure {
379    pub arg: Box<Pattern>,
380    pub body: Box<Expr>,
381}
382
383/// A [Tuple] expression: `(` [`Expr`] (`,` [`Expr`])+ `)`
384#[derive(Clone, Debug, PartialEq, Eq, Hash)]
385pub struct Tuple {
386    pub exprs: Vec<Expr>,
387}
388
389/// A [Struct creation](Structor) expression: [Path] `{` ([Fielder] `,`)* [Fielder]? `}`
390#[derive(Clone, Debug, PartialEq, Eq, Hash)]
391pub struct Structor {
392    pub to: Path,
393    pub init: Vec<Fielder>,
394}
395
396/// A [Struct field initializer] expression: [Sym] (`=` [Expr])?
397#[derive(Clone, Debug, PartialEq, Eq, Hash)]
398pub struct Fielder {
399    pub name: Sym,
400    pub init: Option<Box<Expr>>,
401}
402
403/// An [Array] literal: `[` [`Expr`] (`,` [`Expr`])\* `]`
404#[derive(Clone, Debug, PartialEq, Eq, Hash)]
405pub struct Array {
406    pub values: Vec<Expr>,
407}
408
409/// An Array literal constructed with [repeat syntax](ArrayRep)
410/// `[` [Expr] `;` [Literal] `]`
411#[derive(Clone, Debug, PartialEq, Eq, Hash)]
412pub struct ArrayRep {
413    pub value: Box<Expr>,
414    pub repeat: usize,
415}
416
417/// An address-of expression: `&` `mut`? [`Expr`]
418#[derive(Clone, Debug, PartialEq, Eq, Hash)]
419pub struct AddrOf {
420    pub mutable: Mutability,
421    pub expr: Box<Expr>,
422}
423
424/// A cast expression: [`Expr`] `as` [`Ty`]
425#[derive(Clone, Debug, PartialEq, Eq, Hash)]
426pub struct Cast {
427    pub head: Box<Expr>,
428    pub ty: Ty,
429}
430
431/// A backtick-quoted subexpression-literal
432#[derive(Clone, Debug, PartialEq, Eq, Hash)]
433pub struct Quote {
434    pub quote: Box<Expr>,
435}
436
437/// A [Literal]: 0x42, 1e123, 2.4, "Hello"
438#[derive(Clone, Debug, PartialEq, Eq, Hash)]
439pub enum Literal {
440    Bool(bool),
441    Char(char),
442    Int(u128),
443    Float(u64),
444    String(String),
445}
446
447/// A [Grouping](Group) expression `(` [`Expr`] `)`
448#[derive(Clone, Debug, PartialEq, Eq, Hash)]
449pub struct Group {
450    pub expr: Box<Expr>,
451}
452
453/// A [Block] expression: `{` [`Stmt`]\* [`Expr`]? `}`
454#[derive(Clone, Debug, PartialEq, Eq, Hash)]
455pub struct Block {
456    pub stmts: Vec<Stmt>,
457}
458
459/// An [Assign]ment expression: [`Expr`] ([`ModifyKind`] [`Expr`])\+
460#[derive(Clone, Debug, PartialEq, Eq, Hash)]
461pub struct Assign {
462    pub parts: Box<(Expr, Expr)>,
463}
464
465/// A [Modify]-assignment expression: [`Expr`] ([`ModifyKind`] [`Expr`])\+
466#[derive(Clone, Debug, PartialEq, Eq, Hash)]
467pub struct Modify {
468    pub kind: ModifyKind,
469    pub parts: Box<(Expr, Expr)>,
470}
471
472#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
473pub enum ModifyKind {
474    And,
475    Or,
476    Xor,
477    Shl,
478    Shr,
479    Add,
480    Sub,
481    Mul,
482    Div,
483    Rem,
484}
485
486/// A [Binary] expression: [`Expr`] ([`BinaryKind`] [`Expr`])\+
487#[derive(Clone, Debug, PartialEq, Eq, Hash)]
488pub struct Binary {
489    pub kind: BinaryKind,
490    pub parts: Box<(Expr, Expr)>,
491}
492
493/// A [Binary] operator
494#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
495pub enum BinaryKind {
496    Lt,
497    LtEq,
498    Equal,
499    NotEq,
500    GtEq,
501    Gt,
502    RangeExc,
503    RangeInc,
504    LogAnd,
505    LogOr,
506    LogXor,
507    BitAnd,
508    BitOr,
509    BitXor,
510    Shl,
511    Shr,
512    Add,
513    Sub,
514    Mul,
515    Div,
516    Rem,
517    Call,
518}
519
520/// A [Unary] expression: [`UnaryKind`]\* [`Expr`]
521#[derive(Clone, Debug, PartialEq, Eq, Hash)]
522pub struct Unary {
523    pub kind: UnaryKind,
524    pub tail: Box<Expr>,
525}
526
527/// A [Unary] operator
528#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
529pub enum UnaryKind {
530    Deref,
531    Neg,
532    Not,
533    RangeInc,
534    RangeExc,
535    /// A Loop expression: `loop` [`Block`]
536    Loop,
537    /// Unused
538    At,
539    /// Unused
540    Tilde,
541}
542
543/// A [Member] access expression: [`Expr`] [`MemberKind`]\*
544#[derive(Clone, Debug, PartialEq, Eq, Hash)]
545pub struct Member {
546    pub head: Box<Expr>,
547    pub kind: MemberKind,
548}
549
550/// The kind of [Member] access
551#[derive(Clone, Debug, PartialEq, Eq, Hash)]
552pub enum MemberKind {
553    Call(Sym, Tuple),
554    Struct(Sym),
555    Tuple(Literal),
556}
557
558/// A repeated [Index] expression: a[10, 20, 30][40, 50, 60]
559#[derive(Clone, Debug, PartialEq, Eq, Hash)]
560pub struct Index {
561    pub head: Box<Expr>,
562    pub indices: Vec<Expr>,
563}
564
565/// A local variable declaration [Stmt]
566#[derive(Clone, Debug, PartialEq, Eq, Hash)]
567pub struct Let {
568    pub mutable: Mutability,
569    pub name: Pattern,
570    pub ty: Option<Box<Ty>>,
571    pub init: Option<Box<Expr>>,
572}
573
574/// A `match` expression: `match` `{` ([MatchArm] `,`)* [MatchArm]? `}`
575#[derive(Clone, Debug, PartialEq, Eq, Hash)]
576pub struct Match {
577    pub scrutinee: Box<Expr>,
578    pub arms: Vec<MatchArm>,
579}
580
581/// A single arm of a [Match] expression: [`Pattern`] `=>` [`Expr`]
582#[derive(Clone, Debug, PartialEq, Eq, Hash)]
583pub struct MatchArm(pub Pattern, pub Expr);
584
585/// A [Pattern] meta-expression (any [`ExprKind`] that fits pattern rules)
586#[derive(Clone, Debug, PartialEq, Eq, Hash)]
587pub enum Pattern {
588    Name(Sym),
589    Path(Path),
590    Literal(Literal),
591    Rest(Option<Box<Pattern>>),
592    Ref(Mutability, Box<Pattern>),
593    RangeExc(Box<Pattern>, Box<Pattern>),
594    RangeInc(Box<Pattern>, Box<Pattern>),
595    Tuple(Vec<Pattern>),
596    Array(Vec<Pattern>),
597    Struct(Path, Vec<(Sym, Option<Pattern>)>),
598    TupleStruct(Path, Vec<Pattern>),
599}
600
601/// A [While] expression: `while` [`Expr`] [`Block`] [`Else`]?
602#[derive(Clone, Debug, PartialEq, Eq, Hash)]
603pub struct While {
604    pub cond: Box<Expr>,
605    pub pass: Box<Block>,
606    pub fail: Else,
607}
608
609/// An [If] expression: `if` [`Expr`] [`Block`] [`Else`]?
610#[derive(Clone, Debug, PartialEq, Eq, Hash)]
611pub struct If {
612    pub cond: Box<Expr>,
613    pub pass: Box<Block>,
614    pub fail: Else,
615}
616
617/// A [For] expression: `for` Pattern `in` [`Expr`] [`Block`] [`Else`]?
618#[derive(Clone, Debug, PartialEq, Eq, Hash)]
619pub struct For {
620    pub bind: Pattern,
621    pub cond: Box<Expr>,
622    pub pass: Box<Block>,
623    pub fail: Else,
624}
625
626/// The (optional) `else` clause of a [While], [If], or [For] expression
627#[derive(Clone, Debug, PartialEq, Eq, Hash)]
628pub struct Else {
629    pub body: Option<Box<Expr>>,
630}
631
632/// A [Break] expression: `break` [`Expr`]?
633#[derive(Clone, Debug, PartialEq, Eq, Hash)]
634pub struct Break {
635    pub body: Option<Box<Expr>>,
636}
637
638/// A [Return] expression `return` [`Expr`]?
639#[derive(Clone, Debug, PartialEq, Eq, Hash)]
640pub struct Return {
641    pub body: Option<Box<Expr>>,
642}