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