swamp_script_ast/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/script
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<'_>) -> std::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<Type>,
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<Type>,
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<Type>,
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<Type>,
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 expression: Box<Expression>,
234}
235
236#[derive(Debug, Clone)]
237pub struct NamedStructDef {
238    pub identifier: LocalTypeIdentifierWithOptionalTypeVariables,
239    pub struct_type: AnonymousStructType,
240}
241
242#[derive(Debug, Clone)]
243pub enum Definition {
244    AliasDef(AliasType),
245    NamedStructDef(NamedStructDef),
246    EnumDef(
247        LocalTypeIdentifierWithOptionalTypeVariables,
248        Vec<EnumVariantType>,
249    ),
250    FunctionDef(Function),
251    ImplDef(LocalTypeIdentifierWithOptionalTypeVariables, Vec<Function>),
252    Mod(Mod),
253    Use(Use),
254    // Other
255    Constant(ConstantInfo),
256}
257
258#[derive(Debug, Clone)]
259pub struct ForVar {
260    pub identifier: Node,
261    pub is_mut: Option<Node>,
262}
263
264#[derive(Debug, Clone)]
265pub enum ForPattern {
266    Single(ForVar),
267    Pair(ForVar, ForVar),
268}
269
270impl ForPattern {
271    #[must_use]
272    pub fn any_mut(&self) -> Option<Node> {
273        match self {
274            Self::Single(a) => a.is_mut.clone(),
275            Self::Pair(a, b) => a.is_mut.clone().or_else(|| b.is_mut.clone()),
276        }
277    }
278}
279
280#[derive(Debug, Clone)]
281pub struct IterableExpression {
282    pub expression: Box<MutableOrImmutableExpression>,
283}
284
285#[derive(Clone, Eq, PartialEq)]
286pub struct Variable {
287    pub name: Node,
288    pub is_mutable: Option<Node>,
289}
290
291#[derive(Debug, Clone)]
292pub struct VariableBinding {
293    pub variable: Variable,
294    pub expression: MutableOrImmutableExpression,
295}
296
297#[derive(Debug, Clone)]
298pub struct WhenBinding {
299    pub variable: Variable,
300    pub expression: Option<MutableOrImmutableExpression>,
301}
302
303impl Variable {
304    #[must_use]
305    pub const fn new(name: Node, is_mutable: Option<Node>) -> Self {
306        Self { name, is_mutable }
307    }
308}
309
310// Since this is a helper struct, we want to implement the debug output for it
311// to have it more concise
312impl Debug for Variable {
313    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
314        if let Some(found) = &self.is_mutable {
315            write!(f, "mut {found:?} {:?}", self.name)
316        } else {
317            write!(f, "{:?}", self.name)
318        }
319    }
320}
321
322#[derive(Debug, Eq, Clone, PartialEq)]
323pub struct Parameter {
324    pub variable: Variable,
325    pub param_type: Type,
326}
327
328#[derive(Debug, Clone)]
329pub struct FunctionDeclaration {
330    pub name: Node,
331    pub params: Vec<Parameter>,
332    pub self_parameter: Option<SelfParameter>,
333    pub return_type: Option<Type>,
334    pub generic_variables: Vec<TypeVariable>,
335}
336
337#[derive(Debug, Clone)]
338pub struct FunctionWithBody {
339    pub declaration: FunctionDeclaration,
340    pub body: Expression,
341}
342
343#[derive(Debug, Clone)]
344pub enum Function {
345    Internal(FunctionWithBody),
346    External(FunctionDeclaration),
347}
348
349#[derive(Debug, Clone)]
350pub struct SelfParameter {
351    pub is_mutable: Option<Node>,
352    pub self_node: Node,
353}
354
355#[derive(Debug, PartialEq, Eq)]
356pub enum AssignmentOperatorKind {
357    Compound(CompoundOperatorKind),
358    Assign, // =
359}
360
361#[derive(Debug, PartialEq, Eq, Clone)]
362pub enum CompoundOperatorKind {
363    Add,    // +=
364    Sub,    // -=
365    Mul,    // *=
366    Div,    // /=
367    Modulo, // %=
368}
369
370#[derive(Debug, Clone)]
371pub struct CompoundOperator {
372    pub node: Node,
373    pub kind: CompoundOperatorKind,
374}
375
376#[derive(Debug, Clone)]
377pub enum RangeMode {
378    Inclusive,
379    Exclusive,
380}
381
382#[derive(Debug, Clone)]
383pub struct MutableOrImmutableExpression {
384    pub is_mutable: Option<Node>,
385    pub expression: Expression,
386}
387
388#[derive(Clone)]
389pub struct Expression {
390    pub kind: ExpressionKind,
391    pub node: Node,
392}
393
394impl Debug for Expression {
395    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
396        write!(f, "{:?}{:?}", self.node.span, self.kind)
397    }
398}
399
400#[derive(Debug, Clone)]
401pub enum Postfix {
402    FieldAccess(Node),
403    Subscript(Expression),
404    MemberCall(Node, Vec<MutableOrImmutableExpression>),
405    FunctionCall(Node, Vec<MutableOrImmutableExpression>),
406    OptionalChainingOperator(Node),     // ?-postfix
407    NoneCoalescingOperator(Expression), // ??-postfix
408}
409
410#[derive(Debug, Clone)]
411pub struct PostfixChain {
412    pub base: Box<Expression>,
413    pub postfixes: Vec<Postfix>,
414}
415
416/// Expressions are things that "converts" to a value when evaluated.
417#[derive(Debug, Clone)]
418pub enum ExpressionKind {
419    // Access
420    PostfixChain(PostfixChain),
421
422    // References
423    VariableReference(Variable),
424    ConstantReference(QualifiedConstantIdentifier),
425    StaticMemberFunctionReference(QualifiedTypeIdentifier, Node),
426    IdentifierReference(QualifiedIdentifier),
427
428    // Assignments
429    VariableDefinition(Variable, Option<Type>, Box<MutableOrImmutableExpression>),
430    VariableAssignment(Variable, Box<MutableOrImmutableExpression>),
431    Assignment(Box<Expression>, Box<Expression>),
432    CompoundAssignment(Box<Expression>, CompoundOperator, Box<Expression>),
433    DestructuringAssignment(Vec<Variable>, Box<Expression>),
434
435    // Operators
436    BinaryOp(Box<Expression>, BinaryOperator, Box<Expression>),
437    UnaryOp(UnaryOperator, Box<Expression>),
438
439    //
440    Block(Vec<Expression>),
441    With(Vec<VariableBinding>, Box<Expression>),
442    When(Vec<WhenBinding>, Box<Expression>, Option<Box<Expression>>),
443
444    // Control flow
445    ForLoop(
446        ForPattern,
447        IterableExpression,
448        Option<Box<Expression>>,
449        Box<Expression>,
450    ),
451    WhileLoop(Box<Expression>, Box<Expression>),
452
453    // Compare and Matching
454    If(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
455    Match(Box<MutableOrImmutableExpression>, Vec<MatchArm>),
456    Guard(Vec<GuardExpr>),
457
458    InterpolatedString(Vec<StringPart>),
459
460    // Literals
461    AnonymousStructLiteral(Vec<FieldExpression>, bool),
462    NamedStructLiteral(QualifiedTypeIdentifier, Vec<FieldExpression>, bool),
463    Range(Box<Expression>, Box<Expression>, RangeMode),
464    Literal(LiteralKind),
465    Lambda(Vec<Variable>, Box<Expression>),
466}
467
468#[derive(Debug, Clone)]
469pub struct MatchArm {
470    pub pattern: Pattern,
471    pub expression: Expression,
472}
473
474// Are constructed by themselves
475#[derive(Debug, Clone)]
476pub enum LiteralKind {
477    Int,
478    Float,
479    String(String),
480    Bool,
481    EnumVariant(EnumVariantLiteral),
482    Tuple(Vec<Expression>),
483    Slice(Vec<Expression>),
484    SlicePair(Vec<(Expression, Expression)>),
485    None,
486}
487
488#[derive(Debug, Clone)]
489pub struct FieldExpression {
490    pub field_name: FieldName,
491    pub expression: Expression,
492}
493
494#[derive(Debug, Eq, Hash, Clone, PartialEq)]
495pub struct StructTypeField {
496    pub field_name: FieldName,
497    pub field_type: Type,
498}
499
500#[derive(Debug, Clone)]
501pub enum EnumVariantLiteral {
502    Simple(QualifiedTypeIdentifier, LocalTypeIdentifier),
503    Tuple(
504        QualifiedTypeIdentifier,
505        LocalTypeIdentifier,
506        Vec<Expression>,
507    ),
508    Struct(
509        QualifiedTypeIdentifier,
510        LocalTypeIdentifier,
511        Vec<FieldExpression>,
512        bool,
513    ),
514}
515
516impl EnumVariantLiteral {
517    #[must_use]
518    pub const fn node(&self) -> &Node {
519        match self {
520            EnumVariantLiteral::Simple(ident, _) => &ident.name.0,
521            EnumVariantLiteral::Tuple(ident, _, _) => &ident.name.0,
522            EnumVariantLiteral::Struct(ident, _, _, _) => &ident.name.0,
523        }
524    }
525}
526
527#[derive(Debug, Clone)]
528pub enum EnumVariantType {
529    Simple(Node),
530    Tuple(Node, Vec<Type>),
531    Struct(Node, AnonymousStructType),
532}
533
534#[derive(Debug, PartialEq, Eq, Clone, Hash)]
535pub struct TypeForParameter {
536    pub ast_type: Type,
537    pub is_mutable: bool,
538}
539
540#[derive(Debug, PartialEq, Eq, Clone, Hash)]
541pub enum Type {
542    // Composite
543    Slice(Box<Type>),                // Value array
544    SlicePair(Box<Type>, Box<Type>), // Key : Value
545    AnonymousStruct(AnonymousStructType),
546    Unit,
547    Tuple(Vec<Type>),
548    Function(Vec<TypeForParameter>, Box<Type>),
549
550    Named(QualifiedTypeIdentifier),
551
552    Optional(Box<Type>, Node),
553}
554
555#[derive(Debug, Clone)]
556pub struct BinaryOperator {
557    pub kind: BinaryOperatorKind,
558    pub node: Node,
559}
560
561// Takes a left and right side expression
562#[derive(Debug, Clone)]
563pub enum BinaryOperatorKind {
564    Add,
565    Subtract,
566    Multiply,
567    Divide,
568    Modulo,
569    LogicalOr,
570    LogicalAnd,
571    Equal,
572    NotEqual,
573    LessThan,
574    LessEqual,
575    GreaterThan,
576    GreaterEqual,
577    RangeExclusive,
578}
579
580// Only takes one expression argument
581#[derive(Debug, Clone)]
582pub enum UnaryOperator {
583    Not(Node),
584    Negate(Node),
585}
586
587#[derive(Debug, Clone)]
588pub struct GuardExpr {
589    pub clause: GuardClause,
590    pub result: Expression,
591}
592
593#[derive(Debug, Clone)]
594pub enum GuardClause {
595    Wildcard(Node),
596    Expression(Expression),
597}
598
599// Patterns are used in matching and destructuring
600#[derive(Debug, Clone)]
601pub enum Pattern {
602    Wildcard(Node),
603    NormalPattern(Node, NormalPattern, Option<GuardClause>),
604}
605
606// Patterns are used in matching and destructuring
607#[derive(Debug, Clone)]
608pub enum NormalPattern {
609    PatternList(Vec<PatternElement>),
610    EnumPattern(Node, Option<Vec<PatternElement>>),
611    Literal(LiteralKind),
612}
613
614#[derive(Debug, Clone)]
615pub enum PatternElement {
616    Variable(Variable),
617    Expression(Expression),
618    Wildcard(Node),
619}
620
621#[derive(Debug, Clone)]
622pub enum StringPart {
623    Literal(Node, String),
624    Interpolation(Box<Expression>, Option<FormatSpecifier>),
625}
626
627#[derive(Debug, Clone)]
628pub enum FormatSpecifier {
629    LowerHex(Node),                      // :x
630    UpperHex(Node),                      // :X
631    Binary(Node),                        // :b
632    Float(Node),                         // :f
633    Precision(u32, Node, PrecisionType), // :..2f or :..5s
634}
635
636#[derive(Debug, Clone)]
637pub enum PrecisionType {
638    Float(Node),
639    String(Node),
640}
641
642#[derive()]
643pub struct Module {
644    pub expression: Option<Expression>,
645    pub definitions: Vec<Definition>,
646}
647
648impl Debug for Module {
649    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
650        for definition in &self.definitions {
651            writeln!(f, "{definition:?}")?;
652        }
653
654        if !self.definitions.is_empty() && self.expression.is_some() {
655            writeln!(f, "---")?;
656        }
657
658        if let Some(found_expression) = &self.expression {
659            match &found_expression.kind {
660                ExpressionKind::Block(expressions) => {
661                    for expression in expressions {
662                        writeln!(f, "{expression:?}")?;
663                    }
664                }
665                _ => writeln!(f, "{found_expression:?}")?,
666            }
667        }
668
669        Ok(())
670    }
671}
672
673impl Module {
674    #[must_use]
675    pub const fn new(definitions: Vec<Definition>, expression: Option<Expression>) -> Self {
676        Self {
677            expression,
678            definitions,
679        }
680    }
681
682    #[must_use]
683    pub const fn expression(&self) -> &Option<Expression> {
684        &self.expression
685    }
686
687    #[must_use]
688    pub const fn definitions(&self) -> &Vec<Definition> {
689        &self.definitions
690    }
691
692    #[must_use]
693    pub fn imports(&self) -> Vec<&Use> {
694        let mut use_items = Vec::new();
695
696        for def in &self.definitions {
697            if let Definition::Use(use_info) = def {
698                use_items.push(use_info);
699            }
700        }
701
702        use_items
703    }
704}