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;
10use std::rc::Rc;
11
12#[derive(PartialEq, Eq, Hash, Default, Clone)]
13pub struct SpanWithoutFileId {
14    pub offset: u32,
15    pub length: u16,
16}
17
18impl Debug for SpanWithoutFileId {
19    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
20        write!(f, "<{}:{}>", self.offset, self.length)
21    }
22}
23
24// Common metadata that can be shared across all AST nodes
25#[derive(PartialEq, Eq, Hash, Default, Clone)]
26pub struct Node {
27    pub span: SpanWithoutFileId,
28    // TODO: Add comments and attributes
29}
30
31impl Debug for Node {
32    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
33        write!(f, "{:?}", self.span)
34    }
35}
36
37/// Identifiers ================
38#[derive(Debug, PartialEq, Eq, Hash)]
39pub struct QualifiedTypeIdentifier {
40    pub name: LocalTypeIdentifier,
41    pub module_path: Option<ModulePath>,
42    pub generic_params: Vec<Type>,
43}
44
45impl QualifiedTypeIdentifier {
46    #[must_use]
47    pub fn new(name: LocalTypeIdentifier, module_path: Vec<Node>) -> Self {
48        let module_path = if module_path.is_empty() {
49            None
50        } else {
51            Some(ModulePath(module_path))
52        };
53
54        Self {
55            name,
56            module_path,
57            generic_params: Vec::new(),
58        }
59    }
60
61    #[must_use]
62    pub fn new_with_generics(
63        name: LocalTypeIdentifier,
64        module_path: Vec<Node>,
65        generic_params: Vec<Type>,
66    ) -> Self {
67        let module_path = if module_path.is_empty() {
68            None
69        } else {
70            Some(ModulePath(module_path))
71        };
72
73        Self {
74            name,
75            module_path,
76            generic_params,
77        }
78    }
79}
80
81#[derive(Debug, PartialEq, Eq, Hash, Clone)]
82pub struct QualifiedIdentifier {
83    pub name: Node,
84    pub module_path: Option<ModulePath>,
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 { name, module_path }
97    }
98}
99
100#[derive(Debug, PartialEq, Eq, Hash, Default, Clone)]
101pub struct LocalTypeIdentifier(pub Node);
102
103impl LocalTypeIdentifier {
104    #[must_use]
105    pub const fn new(node: Node) -> Self {
106        Self(node)
107    }
108}
109
110#[derive(PartialEq, Eq, Hash, Debug)]
111pub struct LocalIdentifier(pub Node);
112
113impl LocalIdentifier {
114    #[must_use]
115    pub const fn new(node: Node) -> Self {
116        Self(node)
117    }
118}
119
120#[derive(PartialEq, Eq, Hash, Debug)]
121pub struct ConstantIdentifier(pub Node);
122
123impl ConstantIdentifier {
124    #[must_use]
125    pub const fn new(node: Node) -> Self {
126        Self(node)
127    }
128}
129
130#[derive(Debug, PartialEq, Eq, Hash)]
131pub struct MemberFunctionIdentifier(pub Node);
132
133#[derive(Debug, Eq, Hash, PartialEq)]
134pub struct IdentifierName(pub Node);
135
136#[derive(Debug, Eq, Hash, PartialEq)]
137pub struct FieldName(pub Node);
138
139// =========================
140
141#[derive()]
142pub struct StringConst(pub Node);
143
144#[derive(Debug, Eq, Hash, PartialEq, Clone)]
145pub struct ModulePath(pub Vec<Node>);
146
147impl Default for ModulePath {
148    fn default() -> Self {
149        Self::new()
150    }
151}
152
153impl ModulePath {
154    #[must_use]
155    pub const fn new() -> Self {
156        Self(vec![])
157    }
158}
159
160#[derive(Debug)]
161pub enum UseItem {
162    Identifier(LocalIdentifier),
163    Type(LocalTypeIdentifier),
164}
165
166#[derive(Debug)]
167pub struct Use {
168    pub module_path: ModulePath,
169    pub assigned_path: Vec<String>,
170    pub items: Vec<UseItem>,
171}
172
173#[derive(Debug, Eq, PartialEq, Default)]
174pub struct StructType {
175    pub identifier: LocalTypeIdentifier,
176    pub fields: Vec<FieldType>,
177}
178
179impl StructType {
180    #[must_use]
181    pub const fn new(identifier: LocalTypeIdentifier, fields: Vec<FieldType>) -> Self {
182        Self { identifier, fields }
183    }
184}
185
186#[derive(Debug)]
187pub struct ConstantInfo {
188    pub constant_identifier: ConstantIdentifier,
189    pub expression: Box<Expression>,
190}
191
192#[derive(Debug)]
193pub enum Definition {
194    StructDef(StructType),
195    EnumDef(Node, Vec<EnumVariantType>),
196    FunctionDef(Function),
197    ImplDef(Node, Vec<Function>),
198    Use(Use),
199
200    // Other
201    Comment(Node),
202    Constant(ConstantInfo),
203}
204
205#[derive(Debug)]
206pub struct ForVar {
207    pub identifier: Node,
208    pub is_mut: Option<Node>,
209}
210
211#[derive(Debug)]
212pub enum ForPattern {
213    Single(ForVar),
214    Pair(ForVar, ForVar),
215}
216
217#[derive(Debug)]
218pub struct IteratableExpression {
219    pub expression: Box<Expression>,
220}
221
222#[derive(Eq, PartialEq)]
223pub struct VariableNotMut {
224    pub name: LocalIdentifier,
225}
226
227#[derive(Clone, Eq, PartialEq)]
228pub struct Variable {
229    pub name: Node,
230    pub is_mutable: Option<Node>,
231}
232
233#[derive(Debug)]
234pub struct VariableBinding {
235    pub variable: Variable,
236    pub expression: Expression,
237}
238
239impl Variable {
240    #[must_use]
241    pub const fn new(name: Node, is_mutable: Option<Node>) -> Self {
242        Self { name, is_mutable }
243    }
244}
245
246// Since this is a helper struct, we want to implement the debug output for it
247// to have it more concise
248impl Debug for Variable {
249    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
250        if let Some(found) = &self.is_mutable {
251            write!(f, "mut {found:?} {:?}", self.name)
252        } else {
253            write!(f, "{:?}", self.name)
254        }
255    }
256}
257
258#[derive(Debug, Eq, PartialEq)]
259pub struct Parameter {
260    pub variable: Variable,
261    pub param_type: Type,
262    //    pub is_mutable: Option<Node>,
263}
264
265#[derive(Debug)]
266pub struct FunctionDeclaration {
267    pub name: Node,
268    pub params: Vec<Parameter>,
269    pub self_parameter: Option<SelfParameter>,
270    pub return_type: Option<Type>,
271}
272
273#[derive(Debug)]
274pub struct FunctionWithBody {
275    pub declaration: FunctionDeclaration,
276    pub body: Expression,
277}
278
279#[derive(Debug)]
280pub enum Function {
281    Internal(FunctionWithBody),
282    External(FunctionDeclaration),
283}
284
285#[derive(Debug)]
286pub enum ImplItem {
287    Member(ImplMember),
288    Function(ImplFunction),
289}
290
291#[derive(Debug)]
292pub enum ImplMember {
293    Internal(ImplMemberData),
294    External(ImplMemberSignature),
295}
296
297#[derive(Debug)]
298pub struct ImplMemberSignature {
299    pub name: LocalIdentifier,
300    pub self_param: SelfParameter,
301    pub params: Vec<Parameter>,
302    pub return_type: Type,
303}
304
305#[derive(Debug)]
306pub enum ImplFunction {
307    Internal(FunctionWithBody),
308    External(FunctionDeclaration),
309}
310
311#[derive(Debug)]
312pub struct ImplMemberData {
313    pub name: LocalIdentifier,
314    pub self_param: SelfParameter,
315    pub params: Vec<Parameter>,
316    pub return_type: Type,
317    pub body: Vec<Expression>, // Will be empty for external members
318}
319
320pub type ImplMemberRef = Rc<ImplMember>;
321
322#[derive(Debug)]
323pub struct SelfParameter {
324    pub is_mutable: Option<Node>,
325    pub self_node: Node,
326}
327
328#[derive(Debug, PartialEq, Eq)]
329pub enum CompoundOperatorKind {
330    Add,    // +=
331    Sub,    // -=
332    Mul,    // *=
333    Div,    // /=
334    Modulo, // %=
335}
336
337#[derive(Debug)]
338pub struct CompoundOperator {
339    pub node: Node,
340    pub kind: CompoundOperatorKind,
341}
342
343// A location must be a single Value location. It can never be a slice or something that can have a "variable" size
344#[derive(Debug)]
345pub enum LocationExpression {
346    Variable(Variable),
347    IndexAccess(Box<Expression>, Box<Expression>),
348    FieldAccess(Box<Expression>, Node),
349}
350
351#[derive(Debug)]
352pub enum RangeMode {
353    Inclusive,
354    Exclusive,
355}
356
357/// Expressions are things that "converts" to a value when evaluated.
358#[derive(Debug)]
359pub enum Expression {
360    // Access
361    FieldOrMemberAccess(Box<Expression>, Node),
362    VariableAccess(Variable),
363    ConstantAccess(ConstantIdentifier),
364    FunctionAccess(QualifiedIdentifier),
365
366    MutRef(LocationExpression),
367    IndexAccess(Box<Expression>, Box<Expression>),
368    RangeAccess(Box<Expression>, Box<Expression>, Box<Expression>, RangeMode),
369
370    // Assignments
371    VariableAssignment(Variable, Option<Type>, Box<Expression>),
372    VariableCompoundAssignment(Node, CompoundOperator, Box<Expression>),
373    MultiVariableAssignment(Vec<Variable>, Box<Expression>),
374    IndexAssignment(Box<Expression>, Box<Expression>, Box<Expression>),
375    RangeAssignment(
376        Box<Expression>,
377        Box<Expression>,
378        Box<Expression>,
379        RangeMode,
380        Box<Expression>,
381    ),
382    IndexCompoundAssignment(
383        Box<Expression>,
384        Box<Expression>,
385        CompoundOperator,
386        Box<Expression>,
387    ),
388    FieldAssignment(Box<Expression>, Node, Box<Expression>),
389    FieldCompoundAssignment(Box<Expression>, Node, CompoundOperator, Box<Expression>),
390
391    // Operators
392    BinaryOp(Box<Expression>, BinaryOperator, Box<Expression>),
393    UnaryOp(UnaryOperator, Box<Expression>),
394    NoneCoalesceOperator(Box<Expression>, Box<Expression>),
395
396    // Calls
397    FunctionCall(Box<Expression>, Vec<Expression>),
398    StaticCall(QualifiedTypeIdentifier, Node, Vec<Expression>),
399    StaticCallGeneric(QualifiedTypeIdentifier, Node, Vec<Expression>),
400    MemberOrFieldCall(Box<Expression>, Node, Vec<Expression>),
401
402    Block(Vec<Expression>),
403    With(Vec<VariableBinding>, Box<Expression>),
404
405    // Control flow
406    ForLoop(ForPattern, IteratableExpression, Box<Expression>),
407    WhileLoop(Box<Expression>, Box<Expression>),
408    Return(Option<Box<Expression>>),
409    Break(Node),
410    Continue(Node),
411
412    // Compare and Matching
413    If(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
414    Match(Box<Expression>, Vec<MatchArm>),
415    Guard(Vec<GuardExpr>, Option<Box<Expression>>),
416
417    InterpolatedString(Vec<StringPart>),
418
419    // Instantiation
420    StructInstantiation(QualifiedTypeIdentifier, Vec<FieldExpression>, bool),
421    ExclusiveRange(Box<Expression>, Box<Expression>),
422    InclusiveRange(Box<Expression>, Box<Expression>),
423    Literal(Literal),
424
425    PostfixOp(PostfixOperator, Box<Expression>),
426    StaticMemberFunctionReference(QualifiedTypeIdentifier, Node),
427}
428
429#[derive(Debug)]
430pub struct MatchArm {
431    pub pattern: Pattern,
432    pub expression: Expression,
433}
434
435// Are constructed by themselves
436#[derive(Debug)]
437pub enum Literal {
438    Int(Node),
439    Float(Node),
440    String(Node, String),
441    Bool(Node),
442    EnumVariant(EnumVariantLiteral),
443    Tuple(Vec<Expression>),
444    Array(Vec<Expression>, Node),
445    Map(Vec<(Expression, Expression)>),
446    Unit(Node), // ()
447    None(Node), // none
448}
449
450#[derive(Debug)]
451pub struct FieldExpression {
452    pub field_name: FieldName,
453    pub expression: Expression,
454}
455
456#[derive(Debug, Eq, PartialEq)]
457pub struct FieldType {
458    pub field_name: FieldName,
459    pub field_type: Type,
460}
461
462#[derive(Debug)]
463pub enum EnumVariantLiteral {
464    Simple(QualifiedTypeIdentifier, LocalTypeIdentifier),
465    Tuple(
466        QualifiedTypeIdentifier,
467        LocalTypeIdentifier,
468        Vec<Expression>,
469    ),
470    Struct(
471        QualifiedTypeIdentifier,
472        LocalTypeIdentifier,
473        Vec<FieldExpression>,
474    ),
475}
476
477#[derive(Debug, Default)]
478pub struct AnonymousStructType {
479    pub fields: Vec<FieldType>,
480}
481
482#[derive(Debug)]
483pub enum EnumVariantType {
484    Simple(Node),
485    Tuple(Node, Vec<Type>),
486    Struct(Node, AnonymousStructType),
487}
488
489#[derive(Debug, PartialEq, Eq, Hash)]
490pub struct TypeForParameter {
491    pub ast_type: Type,
492    pub is_mutable: bool,
493}
494
495#[derive(Debug, PartialEq, Eq, Hash)]
496pub enum Type {
497    // Primitives
498    Int(Node),
499    Float(Node),
500    String(Node),
501    Bool(Node),
502    Unit(Node),
503    Any(Node),
504    Generic(Box<Type>, Vec<Type>),
505    Struct(QualifiedTypeIdentifier),
506    Array(Box<Type>),
507    Map(Box<Type>, Box<Type>),
508    Tuple(Vec<Type>),
509    Enum(QualifiedTypeIdentifier),
510    TypeReference(QualifiedTypeIdentifier),
511    Optional(Box<Type>, Node),
512    Function(Vec<TypeForParameter>, Box<Type>),
513}
514
515// Takes a left and right side expression
516#[derive(Debug)]
517pub enum BinaryOperator {
518    Add(Node),
519    Subtract(Node),
520    Multiply(Node),
521    Divide(Node),
522    Modulo(Node),
523    LogicalOr(Node),
524    LogicalAnd(Node),
525    Equal(Node),
526    NotEqual(Node),
527    LessThan(Node),
528    LessEqual(Node),
529    GreaterThan(Node),
530    GreaterEqual(Node),
531    RangeExclusive(Node),
532}
533
534// Only takes one expression argument
535#[derive(Debug)]
536pub enum UnaryOperator {
537    Not(Node),
538    Negate(Node),
539}
540
541// Only takes one expression argument
542#[derive(Debug)]
543pub enum PostfixOperator {
544    Unwrap(Node), // option_operator
545}
546
547#[derive(Debug)]
548pub struct GuardExpr {
549    pub condition: Expression,
550    pub result: Expression,
551}
552
553#[derive(Debug)]
554pub struct GuardClause(pub Expression);
555
556// Patterns are used in matching and destructuring
557#[derive(Debug)]
558pub enum Pattern {
559    Wildcard(Node),
560    NormalPattern(NormalPattern, Option<GuardClause>),
561}
562
563// Patterns are used in matching and destructuring
564#[derive(Debug)]
565pub enum NormalPattern {
566    PatternList(Vec<PatternElement>),
567    EnumPattern(Node, Option<Vec<PatternElement>>),
568    Literal(Literal),
569}
570
571#[derive(Debug)]
572pub enum PatternElement {
573    Variable(Node),
574    Expression(Expression),
575    Wildcard(Node),
576}
577
578#[derive(Debug)]
579pub enum StringPart {
580    Literal(Node, String),
581    Interpolation(Box<Expression>, Option<FormatSpecifier>),
582}
583
584#[derive(Debug)]
585pub enum FormatSpecifier {
586    LowerHex(Node),                      // :x
587    UpperHex(Node),                      // :X
588    Binary(Node),                        // :b
589    Float(Node),                         // :f
590    Precision(u32, Node, PrecisionType), // :..2f or :..5s
591}
592
593#[derive(Debug)]
594pub enum PrecisionType {
595    Float(Node),
596    String(Node),
597}
598
599#[derive()]
600pub struct Module {
601    pub expression: Option<Expression>,
602    pub definitions: Vec<Definition>,
603}
604
605impl Debug for Module {
606    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
607        for definition in &self.definitions {
608            writeln!(f, "{definition:?}")?;
609        }
610
611        if !self.definitions.is_empty() && self.expression.is_some() {
612            writeln!(f, "---")?;
613        }
614
615        if let Some(found_expression) = &self.expression {
616            match found_expression {
617                Expression::Block(expressions) => {
618                    for expression in expressions {
619                        writeln!(f, "{expression:?}")?;
620                    }
621                }
622                _ => writeln!(f, "{found_expression:?}")?,
623            }
624        }
625
626        Ok(())
627    }
628}
629
630impl Module {
631    #[must_use]
632    pub fn new(definitions: Vec<Definition>, expression: Option<Expression>) -> Self {
633        Self {
634            expression,
635            definitions,
636        }
637    }
638
639    #[must_use]
640    pub const fn expression(&self) -> &Option<Expression> {
641        &self.expression
642    }
643
644    #[must_use]
645    pub const fn definitions(&self) -> &Vec<Definition> {
646        &self.definitions
647    }
648
649    #[must_use]
650    pub fn imports(&self) -> Vec<&Use> {
651        let mut use_items = Vec::new();
652
653        for def in &self.definitions {
654            if let Definition::Use(use_info) = def {
655                use_items.push(use_info);
656            }
657        }
658
659        use_items
660    }
661}