swamp_ast/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5pub mod prelude;
6
7use std::fmt;
8use std::fmt::{Debug, Formatter};
9use std::hash::Hash;
10
11#[derive(PartialEq, Eq, Hash, Default, Clone)]
12pub struct SpanWithoutFileId {
13    pub offset: u32,
14    pub length: u16,
15}
16
17impl Debug for SpanWithoutFileId {
18    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
19        write!(f, "<{}:{}>", self.offset, self.length)
20    }
21}
22
23// Common metadata that can be shared across all AST nodes
24#[derive(PartialEq, Eq, Hash, Default, Clone)]
25pub struct Node {
26    pub span: SpanWithoutFileId,
27    // TODO: Add comments and attributes
28}
29
30impl Debug for Node {
31    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
32        write!(f, "{:?}", self.span)
33    }
34}
35
36/// Identifiers ================
37#[derive(Debug, PartialEq, Eq, Clone, Hash)]
38pub struct QualifiedTypeIdentifier {
39    pub name: LocalTypeIdentifier,
40    pub module_path: Option<ModulePath>,
41    pub generic_params: Vec<GenericParameter>,
42}
43
44impl QualifiedTypeIdentifier {
45    #[must_use]
46    pub fn new(name: LocalTypeIdentifier, module_path: Vec<Node>) -> Self {
47        let module_path = if module_path.is_empty() {
48            None
49        } else {
50            Some(ModulePath(module_path))
51        };
52
53        Self {
54            name,
55            module_path,
56            generic_params: Vec::new(),
57        }
58    }
59
60    #[must_use]
61    pub fn new_with_generics(
62        name: LocalTypeIdentifier,
63        module_path: Vec<Node>,
64        generic_params: Vec<GenericParameter>,
65    ) -> Self {
66        let module_path = if module_path.is_empty() {
67            None
68        } else {
69            Some(ModulePath(module_path))
70        };
71
72        Self {
73            name,
74            module_path,
75            generic_params,
76        }
77    }
78}
79
80#[derive(Debug, PartialEq, Eq, Hash, Clone)]
81pub struct QualifiedIdentifier {
82    pub name: Node,
83    pub module_path: Option<ModulePath>,
84    pub generic_params: Vec<GenericParameter>,
85}
86
87impl QualifiedIdentifier {
88    #[must_use]
89    pub fn new(name: Node, module_path: Vec<Node>) -> Self {
90        let module_path = if module_path.is_empty() {
91            None
92        } else {
93            Some(ModulePath(module_path))
94        };
95
96        Self {
97            name,
98            module_path,
99            generic_params: vec![],
100        }
101    }
102
103    #[must_use]
104    pub fn new_with_generics(
105        name: Node,
106        module_path: Vec<Node>,
107        generic_params: Vec<GenericParameter>,
108    ) -> Self {
109        let module_path = if module_path.is_empty() {
110            None
111        } else {
112            Some(ModulePath(module_path))
113        };
114
115        Self {
116            name,
117            module_path,
118            generic_params,
119        }
120    }
121}
122
123#[derive(Debug, PartialEq, Eq, Hash, Default, Clone)]
124pub struct LocalTypeIdentifier(pub Node);
125
126impl LocalTypeIdentifier {
127    #[must_use]
128    pub const fn new(node: Node) -> Self {
129        Self(node)
130    }
131}
132
133#[derive(Debug, PartialEq, Eq, Hash, Default, Clone)]
134pub struct TypeVariable(pub Node);
135
136#[derive(Debug, PartialEq, Eq, Hash, Default, Clone)]
137pub struct LocalTypeIdentifierWithOptionalTypeVariables {
138    pub name: Node,
139    pub type_variables: Vec<TypeVariable>,
140}
141
142#[derive(PartialEq, Eq, Hash, Debug, Clone)]
143pub struct LocalIdentifier(pub Node);
144
145impl LocalIdentifier {
146    #[must_use]
147    pub const fn new(node: Node) -> Self {
148        Self(node)
149    }
150}
151
152#[derive(Debug, PartialEq, Eq, Hash, Default, Clone)]
153pub struct LocalConstantIdentifier(pub Node);
154
155#[derive(Debug, PartialEq, Eq, Clone, Hash)]
156pub struct QualifiedConstantIdentifier {
157    pub name: Node,
158    pub module_path: Option<ModulePath>,
159}
160
161impl QualifiedConstantIdentifier {
162    #[must_use]
163    pub const fn new(name: Node, module_path: Option<ModulePath>) -> Self {
164        Self { name, module_path }
165    }
166}
167
168#[derive(Debug, Eq, Hash, Clone, PartialEq)]
169pub struct FieldName(pub Node);
170
171#[derive(Debug, Eq, Hash, PartialEq, Clone)]
172pub struct ModulePath(pub Vec<Node>);
173
174impl Default for ModulePath {
175    fn default() -> Self {
176        Self::new()
177    }
178}
179
180impl ModulePath {
181    #[must_use]
182    pub const fn new() -> Self {
183        Self(vec![])
184    }
185}
186
187#[derive(Debug, Clone)]
188pub enum ImportItem {
189    Identifier(LocalIdentifier),
190    Type(LocalTypeIdentifier),
191}
192
193#[derive(Debug, Clone)]
194pub enum ImportItems {
195    Nothing,
196    Items(Vec<ImportItem>),
197    All,
198}
199
200#[derive(Debug, Clone)]
201pub struct Mod {
202    pub module_path: ModulePath,
203    pub items: ImportItems,
204}
205
206#[derive(Debug, Clone)]
207pub struct Use {
208    pub module_path: ModulePath,
209    pub items: ImportItems,
210}
211
212#[derive(Debug, Eq, Clone, PartialEq)]
213pub struct AliasType {
214    pub identifier: LocalTypeIdentifier,
215    pub referenced_type: Type,
216}
217
218#[derive(Debug, Eq, PartialEq, Hash, Clone, Default)]
219pub struct AnonymousStructType {
220    pub fields: Vec<StructTypeField>,
221}
222
223impl AnonymousStructType {
224    #[must_use]
225    pub const fn new(fields: Vec<StructTypeField>) -> Self {
226        Self { fields }
227    }
228}
229
230#[derive(Debug, Clone)]
231pub struct ConstantInfo {
232    pub constant_identifier: LocalConstantIdentifier,
233    pub annotation: Option<Type>,
234    pub expression: Box<Expression>,
235}
236
237#[derive(Debug, Clone)]
238pub struct NamedStructDef {
239    pub identifier: LocalTypeIdentifierWithOptionalTypeVariables,
240    pub struct_type: AnonymousStructType,
241}
242
243#[derive(Debug, Clone)]
244pub enum DefinitionKind {
245    AliasDef(AliasType),
246    NamedStructDef(NamedStructDef),
247    EnumDef(
248        LocalTypeIdentifierWithOptionalTypeVariables,
249        Vec<EnumVariantType>,
250    ),
251    FunctionDef(Function),
252    ImplDef(LocalTypeIdentifierWithOptionalTypeVariables, Vec<Function>),
253    Mod(Mod),
254    Use(Use),
255    // Other
256    Constant(ConstantInfo),
257}
258
259#[derive(Debug, Clone)]
260pub struct Definition {
261    pub node: Node,
262    pub kind: DefinitionKind,
263    pub attributes: Vec<Attribute>,
264}
265
266#[derive(Debug, Clone)]
267pub struct ForVar {
268    pub identifier: Node,
269    pub is_mut: Option<Node>,
270}
271
272#[derive(Debug, Clone)]
273pub enum ForPattern {
274    Single(ForVar),
275    Pair(ForVar, ForVar),
276}
277
278impl ForPattern {
279    #[must_use]
280    pub const fn is_key_variable_mut(&self) -> bool {
281        match self {
282            Self::Single(_a) => false,
283            Self::Pair(a, _b) => a.is_mut.is_some(),
284        }
285    }
286    #[must_use]
287    pub fn is_value_mut(&self) -> Option<Node> {
288        match self {
289            Self::Single(a) => a.is_mut.clone(),
290            Self::Pair(a, b) => {
291                assert!(
292                    a.is_mut.is_none(),
293                    "key target var is not allowed to be mut"
294                );
295                b.is_mut.clone()
296            }
297        }
298    }
299}
300
301#[derive(Debug, Clone)]
302pub struct IterableExpression {
303    pub expression: Box<Expression>,
304}
305
306#[derive(Clone, Eq, PartialEq)]
307pub struct Variable {
308    pub name: Node,
309    pub is_mutable: Option<Node>,
310}
311
312#[derive(Debug, Clone)]
313pub struct VariableBinding {
314    pub variable: Variable,
315    pub expression: Option<Expression>,
316}
317
318impl Variable {
319    #[must_use]
320    pub const fn new(name: Node, is_mutable: Option<Node>) -> Self {
321        Self { name, is_mutable }
322    }
323}
324
325// Since this is a helper struct, we want to implement the debug output for it
326// to have it more concise
327impl Debug for Variable {
328    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
329        if let Some(found) = &self.is_mutable {
330            write!(f, "mut {found:?} {:?}", self.name)
331        } else {
332            write!(f, "{:?}", self.name)
333        }
334    }
335}
336
337#[derive(Debug, Eq, Clone, PartialEq)]
338pub struct Parameter {
339    pub variable: Variable,
340    pub param_type: Type,
341}
342
343#[derive(Debug, Clone)]
344pub struct FunctionDeclaration {
345    pub name: Node,
346    pub params: Vec<Parameter>,
347    pub self_parameter: Option<SelfParameter>,
348    pub return_type: Option<Type>,
349}
350
351#[derive(Debug, Clone)]
352pub struct FunctionWithBody {
353    pub attributes: Vec<Attribute>,
354    pub declaration: FunctionDeclaration,
355    pub body: Expression,
356}
357
358#[derive(Debug, Clone)]
359pub enum Function {
360    Internal(FunctionWithBody),
361    External(Node, FunctionDeclaration),
362}
363
364impl Function {
365    #[must_use]
366    pub const fn node(&self) -> &Node {
367        match self {
368            Self::Internal(func_with_body) => &func_with_body.body.node,
369            Self::External(node, _) => node,
370        }
371    }
372}
373
374#[derive(Debug, Clone)]
375pub struct SelfParameter {
376    pub is_mutable: Option<Node>,
377    pub self_node: Node,
378}
379
380#[derive(Debug, PartialEq, Eq)]
381pub enum AssignmentOperatorKind {
382    Compound(CompoundOperatorKind),
383    Assign, // =
384}
385
386#[derive(Debug, PartialEq, Eq, Clone)]
387pub enum CompoundOperatorKind {
388    Add,    // +=
389    Sub,    // -=
390    Mul,    // *=
391    Div,    // /=
392    Modulo, // %=
393}
394
395#[derive(Debug, Clone)]
396pub struct CompoundOperator {
397    pub node: Node,
398    pub kind: CompoundOperatorKind,
399}
400
401#[derive(Debug, Clone)]
402pub enum RangeMode {
403    Inclusive,
404    Exclusive,
405}
406
407#[derive(Clone)]
408pub struct Expression {
409    pub kind: ExpressionKind,
410    pub node: Node,
411}
412
413impl Debug for Expression {
414    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
415        write!(f, "{:?}{:?}", self.node.span, self.kind)
416    }
417}
418
419#[derive(Debug, Clone)]
420pub enum Postfix {
421    FieldAccess(Node),
422    Subscript(Expression),
423    MemberCall(Node, Option<Vec<GenericParameter>>, Vec<Expression>),
424    FunctionCall(Node, Option<Vec<GenericParameter>>, Vec<Expression>),
425    /*
426    AdvancedFunctionCall(
427        Box<Expression>,
428        Node,
429        Option<Vec<GenericParameter>>,
430        Vec<Expression>,
431    ),
432
433     */
434    OptionalChainingOperator(Node),     // ?-postfix
435    NoneCoalescingOperator(Expression), // ??-postfix
436    SubscriptTuple(Expression, Expression),
437}
438
439#[derive(Debug, Clone)]
440pub struct PostfixChain {
441    pub base: Box<Expression>,
442    pub postfixes: Vec<Postfix>,
443}
444
445/// Expressions are things that "converts" to a value when evaluated.
446#[derive(Debug, Clone)]
447pub enum ExpressionKind {
448    // Access
449    PostfixChain(PostfixChain),
450
451    // References
452    ContextAccess, // Context/Lone/Bare-dot
453    VariableReference(Variable),
454    ConstantReference(QualifiedConstantIdentifier),
455    StaticMemberFunctionReference(QualifiedTypeIdentifier, Node),
456    IdentifierReference(QualifiedIdentifier),
457
458    // Assignments
459    VariableDefinition(Variable, Option<Type>, Box<Expression>),
460    VariableAssignment(Variable, Box<Expression>),
461    Assignment(Box<Expression>, Box<Expression>),
462    CompoundAssignment(Box<Expression>, CompoundOperator, Box<Expression>),
463    DestructuringAssignment(Vec<Variable>, Box<Expression>),
464
465    // Operators
466    BinaryOp(Box<Expression>, BinaryOperator, Box<Expression>),
467    UnaryOp(UnaryOperator, Box<Expression>),
468
469    //
470    Block(Vec<Expression>),
471    With(Vec<VariableBinding>, Box<Expression>),
472    When(
473        Vec<VariableBinding>,
474        Box<Expression>,
475        Option<Box<Expression>>,
476    ),
477
478    // Control flow
479    ForLoop(ForPattern, IterableExpression, Box<Expression>),
480    WhileLoop(Box<Expression>, Box<Expression>),
481
482    // Compare and Matching
483    If(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
484    Match(Box<Expression>, Vec<MatchArm>),
485    Guard(Vec<GuardExpr>),
486
487    InterpolatedString(Vec<StringPart>),
488
489    // Literals
490    AnonymousStructLiteral(Vec<FieldExpression>, bool),
491    NamedStructLiteral(QualifiedTypeIdentifier, Vec<FieldExpression>, bool),
492    Range(Box<Expression>, Box<Expression>, RangeMode),
493    Literal(LiteralKind),
494
495    Lambda(Vec<Variable>, Box<Expression>),
496    Error, // Something was wrong in parsing
497}
498
499#[derive(Debug, Clone)]
500pub struct MatchArm {
501    pub pattern: Pattern,
502    pub expression: Expression,
503}
504
505// Are constructed by themselves
506#[derive(Debug, Clone)]
507pub enum LiteralKind {
508    Int,
509    Float,
510    String(String),
511    Bool,
512    EnumVariant(EnumVariantLiteral),
513    Tuple(Vec<Expression>),
514    InternalInitializerList(Vec<Expression>),
515    InternalInitializerPairList(Vec<(Expression, Expression)>),
516    None,
517}
518
519#[derive(Debug, Clone)]
520pub struct FieldExpression {
521    pub field_name: FieldName,
522    pub expression: Expression,
523}
524
525#[derive(Debug, Eq, Hash, Clone, PartialEq)]
526pub struct StructTypeField {
527    pub field_name: FieldName,
528    pub field_type: Type,
529}
530
531#[derive(Debug, Clone)]
532pub enum EnumVariantLiteral {
533    Simple(QualifiedTypeIdentifier, LocalTypeIdentifier),
534    Tuple(
535        QualifiedTypeIdentifier,
536        LocalTypeIdentifier,
537        Vec<Expression>,
538    ),
539    Struct(
540        QualifiedTypeIdentifier,
541        LocalTypeIdentifier,
542        Vec<FieldExpression>,
543        bool,
544    ),
545}
546
547impl EnumVariantLiteral {
548    #[must_use]
549    pub const fn node(&self) -> &Node {
550        match self {
551            Self::Tuple(ident, _, _) | Self::Struct(ident, _, _, _) | Self::Simple(ident, _) => {
552                &ident.name.0
553            }
554        }
555    }
556}
557
558#[derive(Debug, Clone)]
559pub enum EnumVariantType {
560    Simple(Node),
561    Direct(Node, Type),
562    Tuple(Node, Vec<Type>),
563    Struct(Node, AnonymousStructType),
564}
565
566#[derive(Debug, PartialEq, Eq, Clone, Hash)]
567pub struct TypeForParameter {
568    pub ast_type: Type,
569    pub is_mutable: bool,
570}
571
572#[derive(Debug, Clone, PartialEq, Eq, Hash)]
573pub enum GenericParameter {
574    Type(Type),
575    UnsignedInt(Node),
576    UnsignedTupleInt(Node, Node),
577}
578
579impl GenericParameter {
580    #[must_use]
581    pub fn get_unsigned_int_node(&self) -> &Node {
582        let Self::UnsignedInt(node) = self else {
583            panic!("wasn't unsigned int")
584        };
585        node
586    }
587
588    #[must_use]
589    pub fn get_unsigned_int_tuple_nodes(&self) -> (&Node, &Node) {
590        let Self::UnsignedTupleInt(first, second) = self else {
591            panic!("wasn't unsigned int tuple")
592        };
593        (first, second)
594    }
595}
596
597impl GenericParameter {
598    #[must_use]
599    pub fn get_type(&self) -> &Type {
600        let Self::Type(ty) = self else {
601            panic!("{}", format!("wasn't type {self:?}"))
602        };
603        ty
604    }
605}
606
607#[derive(Debug, PartialEq, Eq, Clone, Hash)]
608pub enum Type {
609    // Composite
610    FixedCapacityArray(Box<Type>, Node),          // `[T; N]`
611    Slice(Box<Type>), // `[T]`. Contiguous memory segments without ownership, Unsized Type (DST) that has inline data
612    FixedCapacityMap(Box<Type>, Box<Type>, Node), // `[K:V;N]`
613    DynamicLengthMap(Box<Type>, Box<Type>), // `[K:V]`
614
615    AnonymousStruct(AnonymousStructType),
616    Unit,
617    Tuple(Vec<Type>),
618    Function(Vec<TypeForParameter>, Box<Type>),
619
620    Named(QualifiedTypeIdentifier),
621
622    Optional(Box<Type>, Node),
623}
624
625#[derive(Debug, Clone)]
626pub struct BinaryOperator {
627    pub kind: BinaryOperatorKind,
628    pub node: Node,
629}
630
631// Takes a left and right side expression
632#[derive(Debug, Clone)]
633pub enum BinaryOperatorKind {
634    Add,
635    Subtract,
636    Multiply,
637    Divide,
638    Modulo,
639    LogicalOr,
640    LogicalAnd,
641    Equal,
642    NotEqual,
643    LessThan,
644    LessEqual,
645    GreaterThan,
646    GreaterEqual,
647}
648
649// Only takes one expression argument
650#[derive(Debug, Clone)]
651pub enum UnaryOperator {
652    Not(Node),
653    Negate(Node),
654    BorrowMutRef(Node),
655}
656
657#[derive(Debug, Clone)]
658pub struct GuardExpr {
659    pub clause: GuardClause,
660    pub result: Expression,
661}
662
663#[derive(Debug, Clone)]
664pub enum GuardClause {
665    Wildcard(Node),
666    Expression(Expression),
667}
668
669// Patterns are used in matching and destructuring
670#[derive(Debug, Clone)]
671pub enum Pattern {
672    Wildcard(Node),
673    ConcretePattern(Node, ConcretePattern, Option<GuardClause>),
674}
675
676#[derive(Debug, Clone)]
677pub enum ConcretePattern {
678    EnumPattern(Node, DestructuringPattern), // VariantName <destructuring>
679    Literal(LiteralKind),                    // 42 or "hello" or 2.42
680}
681
682#[derive(Debug, Clone)]
683pub enum PatternVariableOrWildcard {
684    Variable(Variable),
685    Wildcard(Node),
686}
687
688// Which destructuring to use, or none
689#[derive(Debug, Clone)]
690pub enum DestructuringPattern {
691    /// A struct-like variant: `Variant { field, .. }`
692    Struct { fields: Vec<Variable> },
693
694    /// A tuple-like variant: `Variant(item, ..)`
695    Tuple {
696        elements: Vec<PatternVariableOrWildcard>,
697    },
698
699    /// A single payload variable: `Some(payload)` or `Ok(value)`
700    None { variable: Variable },
701
702    /// A unit variant with no payload: `Red`, `Green`, `Blue`
703    Unit,
704}
705
706#[derive(Debug, Clone)]
707pub enum StringPart {
708    Literal(Node, String),
709    Interpolation(Box<Expression>, Option<FormatSpecifier>),
710}
711
712#[derive(Debug, Clone)]
713pub enum FormatSpecifier {
714    LowerHex(Node),                      // :x
715    UpperHex(Node),                      // :X
716    Binary(Node),                        // :b
717    Float(Node),                         // :f
718    Precision(u32, Node, PrecisionType), // :..2f or :..5s
719}
720
721#[derive(Debug, Clone)]
722pub enum PrecisionType {
723    Float(Node),
724    String(Node),
725}
726
727#[derive(Debug, Clone)]
728pub enum AttributeArg {
729    /// A path/identifier, e.g. `Debug` or `unix`
730    Path(QualifiedIdentifier),
731    /// A literal value, e.g. `"foo"`, `42`, `true`
732    Literal(AttributeValue),
733    /// A function call, e.g. `any(unix, windows)` or `rename = "foo"`
734    Function(QualifiedIdentifier, Vec<AttributeArg>),
735}
736
737#[derive(Debug, Clone)]
738pub enum AttributeLiteralKind {
739    Int,
740    String(String),
741    Bool,
742}
743
744#[derive(Debug, Clone)]
745pub enum AttributeValue {
746    Literal(Node, AttributeLiteralKind),
747    Path(QualifiedIdentifier),
748    Function(QualifiedIdentifier, Vec<AttributeArg>),
749}
750
751#[derive(Debug, Clone)]
752pub struct Attribute {
753    pub is_inner: bool,
754    pub path: QualifiedIdentifier,
755    pub args: Vec<AttributeArg>,
756    pub node: Node,
757}
758
759#[derive()]
760pub struct Module {
761    pub expression: Option<Expression>,
762    pub definitions: Vec<Definition>,
763}
764
765impl Debug for Module {
766    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
767        for definition in &self.definitions {
768            writeln!(f, "{definition:?}")?;
769        }
770
771        if !self.definitions.is_empty() && self.expression.is_some() {
772            writeln!(f, "---")?;
773        }
774
775        if let Some(found_expression) = &self.expression {
776            match &found_expression.kind {
777                ExpressionKind::Block(expressions) => {
778                    for expression in expressions {
779                        writeln!(f, "{expression:?}")?;
780                    }
781                }
782                _ => writeln!(f, "{found_expression:?}")?,
783            }
784        }
785
786        Ok(())
787    }
788}
789
790impl Module {
791    #[must_use]
792    pub const fn new(definitions: Vec<Definition>, expression: Option<Expression>) -> Self {
793        Self {
794            expression,
795            definitions,
796        }
797    }
798
799    #[must_use]
800    pub const fn expression(&self) -> &Option<Expression> {
801        &self.expression
802    }
803
804    #[must_use]
805    pub const fn definitions(&self) -> &Vec<Definition> {
806        &self.definitions
807    }
808
809    #[must_use]
810    pub fn imports(&self) -> Vec<&Use> {
811        let mut use_items = Vec::new();
812
813        for def in &self.definitions {
814            if let DefinitionKind::Use(use_info) = &def.kind {
815                use_items.push(use_info);
816            }
817        }
818
819        use_items
820    }
821}