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