aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/ast.rs
blob: ed7a01a036680884671b2e0ba10f4181d9db0149 (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
117
118
/// 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 { // todo: multiple params, effects
        from: Box<Type>,
        to: Box<Type>
    },
    Struct(Vec<(Id, Box<Type>)>),
    Tuple(Vec<(Option<Id>, 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>),
    Pointer(Box<Type>),
    Distinct(Box<Type>), // todo: not sure
    Mutable(Box<Type>), // parameters only
    Static(Box<Type>),  // parameters only
    Alias { // todo: this is wrong
        id: Id,
        generics: Vec<Type>
    }
}

/// 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<(Id, Expr)>), // field, value
    Tuple(Vec<(Option<Id>, Expr)>), // field, value
    List(Vec<Expr>), // arrays, slices, lists
}

/// 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<(Id, Option<Type>)>, // id, kind
        params: Vec<(Id, Type)>, // id, kind
        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> },
}

/// 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 { pub cond: Expr, pub body: Vec<Expr> }
pub struct CatchBranch { pub exceptions: Vec<Id>, pub binding: Option<Id>, pub body: Vec<Expr> }
pub struct MatchBranch { pub pattern: Pattern, pub guard: Option<Expr>, pub body: Vec<Expr> }

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