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
|
/// Representation of Tokens, function names, the like...
pub type Id = String;
/// Puck's fundamental types.
#[derive(Clone, PartialEq)]
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(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>), // parameters only
Static(Box<Type>), // parameters only
Alias { // todo: this is wrong
id: Id,
generics: Vec<Type>
}
}
/// Function signatures.
#[derive(Clone, PartialEq)]
pub struct Sig {
pub effect: Option<Id>,
pub id: Id,
pub generics: Vec<(Id, Option<Type>)>,
pub parameters: Vec<Type>,
pub kind: 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>
},
Func {
public: bool,
effect: Option<Id>,
id: Id,
generics: Vec<(Id, Option<Type>)>, // id, kind
parameters: Vec<(Id, Type)>, // id, kind
kind: Type,
body: Vec<Expr>
},
Macro {
public: bool,
id: Id,
generics: Vec<(Id, Option<Type>)>, // id, kind
parameters: Vec<(Id, Option<Type>)>, // id, kind
kind: Option<Type>,
body: Vec<Expr>
},
TypeDecl { id: Id, generics: Vec<(Id, Option<Type>)>, 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, 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),
}
|