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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
/// Representation of Tokens, function names, the like...
pub type Id = String;
/// Puck's fundamental types.
#[derive(Clone, PartialEq)]
pub enum Type {
Void, Never, Any,
Integer, Float, String, // char et al are defined later
Func { // future: effects
from: Vec<Type>,
to: Vec<Type>
},
Struct(Vec<(Id, Type)>),
Tuple(Vec<(Option<Id>, Type)>),
Union(Vec<(Id, Type)>),
Interface(Vec<Sig>),
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>), Static(Box<Type>), // parameters only
Alias { // todo: this is wrong
id: Id,
generics: Vec<Type>
}
}
/// Function signatures.
#[derive(Clone, PartialEq)]
pub struct Sig {
pub id: Id,
pub generics: Vec<(Id, Option<Type>)>,
pub parameters: Vec<Type>,
pub kind: 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.
pub enum Binding { // todo: excessive use of Option<Type>
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>
},
Func {
public: bool,
id: Id,
generics: Vec<(Id, Option<Type>)>,
parameters: Vec<(Id, Type)>,
kind: Type,
body: Vec<Expr>
},
Macro {
public: bool,
id: Id,
generics: Vec<(Id, Option<Type>)>,
parameters: Vec<(Id, Option<Type>)>,
kind: Option<Type>,
body: Vec<Expr>
},
TypeDecl { id: Id, generics: Vec<(Id, Option<Type>)>, alias: Type },
Use { modules: Vec<Id> }, // todo: aliases? anything else fancy?
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: Vec<Expr>
},
Try {
body: Vec<Expr>,
catches: Vec<CatchBranch>,
finally: 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, Option<Id>)>,
pub body: Vec<Expr>
}
pub struct MatchBranch {
pub patterns: Vec<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),
}
pub type Ast = Vec<Expr>;
|