aboutsummaryrefslogtreecommitdiff
path: root/src/ast.rs
blob: 92cabac080f112fdb04437c54cd3db08b6b5df05 (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
/// 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<(Id, Expr)>),
    Tuple(Vec<(Option<Id>, Expr)>),
    List(Vec<Expr>), // arrays, slices, lists
}

/// Expressions introduce a new binding or bindings, in some regard.
pub enum Binding {
    Let {
        // Most usages of Let, Var, Const have the id as just an Ident.
        // But making it a Pattern supports ex. `let (a, b) = ...`
        // And also unpacking: ex. `let Object(a, b) = ...`
        id: Pattern,
        kind: Option<Type>,
        value: Box<Expr>
    },
    Var {
        id: Pattern,
        kind: Option<Type>,
        value: Option<Box<Expr>> // variable bindings can be delayed
    },
    Const {
        id: Pattern,
        kind: Option<Type>,
        value: Box<Expr>
    },
    Func {
        public: bool,
        effect: Option<Id>,
        id: Id,
        generics: Vec<(Id, Option<Type>)>,
        params: Vec<(Id, Type)>,
        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...
    Cond {
        // cond, body
        branches: Vec<(Expr, Vec<Expr>)>,
        else_body: Option<Vec<Expr>>
    },
    Match {
        item: Box<Expr>,
        // pattern, guard, branch
        branches: Vec<(Pattern, Option<Expr>, Expr)> // todo
    },
    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> },
}

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