aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/ast.rs
blob: 6c7963e37160fd3bba794cc1b2d50cd4894eb606 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/// Representation of Tokens, function names, the like...
pub type Id = String;

/// Puck's fundamental types.
pub enum Type {
    Void, Never,
    Integer, Float, String, // char et al are defined later
    Func{from: Box<Type>, to: Box<Type>}, // todo: multiple params, effects
    Struct(Vec<(Id, Box<Type>)>),
    Tuple(Vec<(Option<String>, Box<Type>)>),
    Union(Vec<(Id, Box<Type>)>),
    Interface {
        funcs: Vec<Sig>,
        for_type: Option<Box<Type>>,
    },
    Array{size: usize, kind: Box<Type>},
    List(Box<Type>),
    Slice(Box<Type>), // todo: plus ownership
    Reference(Box<Type>),
    Mutable(Box<Type>), // parameters only
    Static(Box<Type>),  // parameters only
    Alias{ id: Id, params: Vec<Type> }, // todo: this is wrong
}

/// Function signatures.
pub struct Sig {
    effect: Option<Id>,
    id: Id,
    generics: Vec<(Id, Option<Type>)>,
    params: Vec<Type>,
    result: Option<Type>
}

/// Patterns are recognizable given zero context.
/// This is why there is a generic Number term and no Bool term.
/// Also can be considered to be a Term/Value.
pub enum Pattern {
    Ident(Id), // type aliases, union variants, calls...
    Number(i64), Float(f64),
    Char(char), String(String),
    Struct(Vec<StructPattern>),
    Tuple(Vec<TuplePattern>),
    List(Vec<Expr>), // arrays, slices, lists
}

pub struct StructPattern { field: Id, value: Expr }
pub struct TuplePattern { field: Option<Id>, value: Expr }

/// Expressions introduce a new binding or bindings, in some regard.
pub enum Binding {
    Let {
        id: Pattern, // id: Pattern supports ex. `let (a, b) = ...`
        kind: Option<Type>,
        value: Box<Expr>
    },
    Var {
        id: Pattern,
        kind: Option<Type>,
        value: Option<Box<Expr>> // variable bindings can be delayed
    },
    Const {
        public: bool,
        id: Pattern,
        kind: Option<Type>,
        value: Box<Expr>
    },
    FuncDecl {
        public: bool,
        effect: Option<Id>,
        id: Id,
        generics: Vec<GenericDecl>,
        params: Vec<ParamDecl>,
        kind: Type,
        body: Vec<Expr>
    },
    TypeDecl { id: Id, generics: Vec<Id>, alias: Type },
    Import { from: Option<Id>, imports: Vec<Id>, alias: Option<Id> },
    Module { id: Id, body: Vec<Expr> },
}

pub struct GenericDecl { id: Id, kind: Option<Type> }
pub struct ParamDecl { id: Id, kind: Type }

/// Expressions related to control flow.
pub enum Control {
    Call { id: Id, params: Vec<Expr> }, // function calls, macro invocations, field access...
    If {
        branches: Vec<CondBranch>,
        else_body: Option<Vec<Expr>>
    },
    Try {
        body: Vec<Expr>,
        catches: Vec<CatchBranch>,
        finally: Option<Vec<Expr>>
    },
    Match {
        item: Pattern,
        branches: Vec<MatchBranch>
    },
    Block { id: Option<Id>, body: Vec<Expr> },
    Static { body: Vec<Expr> },
    For { binding: Pattern, range: Box<Expr>, body: Vec<Expr> },
    While { cond: Box<Expr>, body: Vec<Expr> },
    Loop { body: Vec<Expr> },
}

pub struct CondBranch { cond: Expr, body: Vec<Expr> }
pub struct CatchBranch { exceptions: Vec<Id>, binding: Option<Id>, body: Vec<Expr> }
pub struct MatchBranch { pattern: Pattern, guard: Option<Expr>, body: Vec<Expr> }

/// Expressions are either Patterns, Bindings, or Control flow constructs.
pub enum Expr {
    Pattern(Pattern),
    Binding(Binding),
    Control(Control),
}