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