Skip to content

Commit 3db3935

Browse files
authored
added comments to IR.zig (#7688)
* added comments * improved comments * top level comment, cleanup Signed-off-by: Anton-4 <[email protected]> * fmt --------- Signed-off-by: Anton-4 <[email protected]>
1 parent 30bc27a commit 3db3935

File tree

1 file changed

+117
-52
lines changed
  • src/build/specialize_types

1 file changed

+117
-52
lines changed

src/build/specialize_types/IR.zig

Lines changed: 117 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
//! The intermediate representation (IR) for a Roc module that has been monomorphized.
2+
//!
3+
//! Monomorphization, also known as type specialization, is the process of creating a distinct copy
4+
//! of each instance of a generic function or value based on all specific usages in a program.
5+
//! For example; a function with the type `Num a -> Num a` may only be called in the program with a
6+
//! `U64` and a `I64`. Specialization will then create two functions with the types `U64 -> U64` and
7+
//! `I64 -> I64`.
8+
//! This trades off some compile time for a much better runtime performance, since we don't need to
9+
//! look up which implementation to call at runtime (AKA dynamic dispatch).
10+
//!
11+
//! Doing type specialization as the first build stage helps simplify compilation of lambda sets, or
12+
//! values captured by closures.
13+
//!
14+
//! The values in this module represent all data for a single type-specialized module, except for
15+
//! interned data which resides in the `ModuleEnv`. This IR has a very similar structure to the next
16+
//! stage's IR (`lift_functions`), but not quite the same. For now, we have designed our compiler
17+
//! stages to be simple and correct at the cost of not deduplicating similar code. In the future,
18+
//! we may decide to combine the IRs of some build stages to avoid needing to convert lots of
19+
//! equivalent data.
20+
121
const std = @import("std");
222
const base = @import("../../base.zig");
323
const types_module = @import("../../types.zig");
@@ -13,13 +33,20 @@ const Self = @This();
1333
env: *base.ModuleEnv,
1434
exposed_values: std.AutoHashMap(Ident.Idx, Expr.Idx),
1535
exposed_functions: std.AutoHashMap(Ident.Idx, Function),
36+
/// All types in the module
1637
types: Type.List,
38+
/// All expressions in the module
1739
exprs: Expr.List,
40+
/// All typed expressions in the module
1841
typed_exprs: Expr.Typed.List,
42+
/// All patterns (for pattern matching, destructuring, var name) in the module
1943
patterns: Pattern.List,
44+
/// All typed patterns in the module
2045
typed_patterns: Pattern.Typed.List,
46+
/// All typed identifiers in the module
2147
typed_idents: TypedIdent.List,
22-
when_branches: WhenBranch.List,
48+
/// All match branches in the module
49+
match_branches: MatchBranch.List,
2350

2451
pub fn init(env: *base.ModuleEnv) Self {
2552
return Self{
@@ -32,7 +59,7 @@ pub fn init(env: *base.ModuleEnv) Self {
3259
.patterns = .{},
3360
.typed_patterns = .{},
3461
.typed_idents = .{},
35-
.when_branches = .{},
62+
.match_branches = .{},
3663
};
3764
}
3865

@@ -45,209 +72,247 @@ pub fn deinit(self: *Self) void {
4572
self.patterns.deinit(self.env.gpa);
4673
self.typed_patterns.deinit(self.env.gpa);
4774
self.typed_idents.deinit(self.env.gpa);
48-
self.when_branches.deinit(self.env.gpa);
75+
self.match_branches.deinit(self.env.gpa);
4976
}
5077

51-
/// todo
78+
/// Represents a concrete (no type variables,...) Roc type e.g. `U64`, `Str`, `List(U64)`.
5279
pub const Type = union(enum) {
80+
/// e.g. Int, Bool, Str
5381
primitive: types_module.Primitive,
82+
/// Holds unknown Roc type for use with platform or can be used to improve perf in rare cases https://www.roc-lang.org/builtins/Box
5483
box: Type.Idx,
84+
/// e.g. List(U64)
5585
list: Type.Idx,
86+
/// Records, tuples and tag union payload become structs
5687
@"struct": Type.NonEmptySlice,
88+
/// e.g. `[Red, Yellow, Green]`
5789
tag_union: Type.NonEmptySlice,
90+
/// A function that has a return value and 0 or more arguments
5891
func: struct {
92+
/// A slice containing the return value followed by the arguments
5993
ret_then_args: Type.NonEmptySlice,
6094
},
61-
/// todo
95+
/// list of Type
6296
pub const List = collections.SafeList(@This());
63-
/// todo
97+
/// Index into Type.List
6498
pub const Idx = List.Idx;
65-
/// todo
99+
/// Sublist reference of Type.List
66100
pub const Slice = List.Slice;
67-
/// todo
101+
/// Sublist reference into Type.List that is guaranteed to be non-empty
68102
pub const NonEmptySlice = List.NonEmptySlice;
69103
};
70104

71-
/// todo
105+
/// Represents a Roc expression
72106
pub const Expr = union(enum) {
107+
/// e.g. `x = 1`
73108
let: Def,
109+
/// e.g. "abc"
74110
str: StringLiteral,
111+
/// e.g. 123
75112
number: base.Literal.Num,
113+
/// e.g. [1, 2, 3]
76114
list: struct {
77115
elem_type: Type.Idx,
78116
elems: Expr.Slice,
79117
},
118+
/// e.g. `pf.Stdout` or `x`
80119
lookup: struct {
81120
ident: Ident.Idx,
82121
type: Type.Idx,
83122
},
84-
123+
/// e.g `fibo(5)`
85124
call: struct {
86125
fn_type: Type.Idx,
126+
// ???
87127
fn_expr: Expr.Idx,
88128
args: Expr.Typed.Slice,
89129
},
90-
130+
/// e.g. `|x| x * 2`
91131
lambda: struct {
92132
fn_type: Type.Idx,
93133
arguments: Pattern.Typed.Slice,
94134
body: Expr.Idx,
95135
recursive: base.Recursive,
96136
},
97-
137+
/// Represents the empty record `{}`
98138
unit,
99-
139+
/// Record or tuple becomes struct
100140
@"struct": Expr.NonEmptySlice,
101-
141+
/// Record or tuple access
102142
struct_access: struct {
103143
record_expr: Expr.Idx,
104144
record_type: Type.Idx,
105145
field_type: Type.Idx,
106146
field_id: Ident.Idx,
107147
},
108-
148+
/// e.g. `Ok(1)`
109149
tag: struct {
150+
/// Numeric representation of the tag variant
110151
discriminant: u16,
152+
/// e.g. `Result` for `Ok(1)`
111153
tag_union_type: Type.Idx,
154+
/// e.g. `1` for `Ok(1)`
112155
args: Expr.Typed.Slice,
113156
},
114-
115-
when: struct {
116-
/// The value being matched on
157+
/// from pattern matching with `match`
158+
match: struct {
159+
/// The value being matched on, e.g. `match value is`
117160
value: Expr.Idx,
118161
/// The type of the value being matched on
119162
value_type: Type.Idx,
120-
/// The return type of all branches and thus the whole when expression
163+
/// The return type of all branches and thus the whole match expression
121164
branch_type: Type.Idx,
122-
/// The branches of the when expression
123-
branches: WhenBranch.NonEmptySlice,
165+
/// The branches of the match expression
166+
branches: MatchBranch.NonEmptySlice,
124167
},
125168

126169
compiler_bug: Problem.Compiler,
127170

128-
/// todo
171+
/// List of Expr
129172
pub const List = collections.SafeList(@This());
130-
/// todo
173+
/// Index into an Expr.List
131174
pub const Idx = List.Idx;
132-
/// todo
175+
/// Sublist reference of Expr.List
133176
pub const Slice = List.Slice;
134-
/// todo
177+
/// Sublist reference into Expr.List that is guaranteed to be non-empty
135178
pub const NonEmptySlice = List.NonEmptySlice;
136-
/// todo
179+
/// Expression with accompanying type
137180
pub const Typed = struct {
138181
expr: Expr.Idx,
139182
type: Type.Idx,
140-
/// todo
183+
/// List of Expr.Typed
141184
pub const List = collections.SafeMultiList(@This());
142-
/// todo
185+
/// Sublist reference into Expr.Typed.List
143186
pub const Slice = Typed.List.Slice;
144187
};
145188
};
146189

147190
/// A definition, e.g. `x = foo`
148191
pub const Def = struct {
192+
/// For what's to the left of `=`, could be a var name or destructuring
149193
pattern: Pattern.Idx,
150-
/// Named variables in the pattern, e.g. `a` in `Ok a ->`
194+
/// Named variables in the pattern, e.g. `a` and `b` in `{a, b} = ...`
151195
pattern_vars: TypedIdent.Slice,
196+
/// expression to the right of `=`
152197
expr: Expr.Idx,
198+
/// type of the expression to the right of `=`
153199
expr_type: Type.Idx,
154-
/// todo
200+
/// List of Def
155201
pub const List = collections.SafeMultiList(@This());
156-
/// todo
202+
/// Sublist reference into Def.List
157203
pub const Slice = List.Slice;
158204
};
159205

160-
/// todo
161-
pub const WhenBranch = struct {
206+
/// Branch of a `match` expression, e.g. `Green -> "green"`
207+
pub const MatchBranch = struct {
162208
/// The pattern(s) to match the value against
163209
patterns: Pattern.NonEmptySlice,
164210
/// A boolean expression that must be true for this branch to be taken
165211
guard: ?Expr.Idx,
166212
/// The expression to produce if the pattern matches
167213
value: Expr.Idx,
168-
/// todo
214+
/// List of MatchBranch
169215
pub const List = collections.SafeList(@This());
170-
/// todo
216+
/// Reference to non-empty sublist into MatchBranch.List
171217
pub const NonEmptySlice = List.NonEmptySlice;
172218
};
173219

174-
/// todo
220+
/// e.g. `|x| x * 2`
175221
pub const Function = struct {
176222
args: Pattern.Slice,
177223
return_type: Type.Idx,
224+
/// ??? Is expr the body of the function?
178225
expr: Expr.Idx,
179226
};
180227

181-
/// todo
228+
/// For record/tuple destructuring, e.g. `{ x, y: 123 } -> ...` contains two StructDestruct: one for `x` and one for `y`.
182229
pub const StructDestruct = struct {
183230
ident: Ident.Idx,
184231
field: Ident.Idx,
185232
kind: Kind,
186-
/// todo
187233
pub const Kind = union(enum) {
234+
/// e.g `x` in `{ x, y: 123 }` is required
188235
required,
236+
/// e.g. .{ .num_literal = 123 } in `{ x, y: 123 }`. Keeping the value of y around is not required
189237
guard: Pattern.Typed,
190238
};
191-
/// todo
239+
/// List of StructDestruct
192240
pub const List = collections.SafeMultiList(@This());
193-
/// todo
241+
/// Reference to sublist into StructDestruct.List
194242
pub const Slice = List.Slice;
195243
};
196244

197-
/// todo
245+
/// Represents a pattern used in pattern matching e.g. `Ok x` as part of a match branch
198246
pub const Pattern = union(enum) {
247+
/// e.g. `x`
199248
identifier: Ident.Idx,
249+
/// e.g. `{ x, y } as data` in `{ x, y } as data -> call(data)`
200250
as: struct {
251+
/// e.g. `{ x, y }` in `{ x, y } as data`
201252
pattern: Pattern.Idx,
253+
/// e.g. `data` in `{ x, y } as data`
202254
ident: Ident.Idx,
203255
},
204256
str_literal: StringLiteral.Idx,
205257
number_literal: base.Literal.Num,
258+
/// e.g. `Ok(x)` in `Ok(x) ->`
206259
applied_tag: struct {
260+
/// Type of tag union e.g. `Result`
207261
tag_union_type: Type.Idx,
208262
tag_name: Ident.Idx,
263+
/// e.g. `x` in `Ok(x)`
209264
args: Pattern.Slice,
210265
},
266+
/// e.g. `{x, y}` in `{x, y} -> Point(x, y)`
211267
struct_destructure: struct {
212268
struct_type: Type.Idx,
269+
/// e.g. for `{ x, y: 123 } -> ...` there are two StructDestruct; one for x and one for y
213270
destructs: StructDestruct.Slice,
271+
/// e.g. `..` in `{x, y, ..}`
214272
opt_spread: ?Pattern.Typed,
215273
},
274+
/// e.g. [Foo, Bar, ..]
216275
list: struct {
217276
elem_type: Type.Idx,
277+
/// e.g. Foo and Bar in `[Foo, Bar, ..]`
218278
patterns: Pattern.Slice,
219-
279+
/// refers to e.g. `..tail` in `[head, ..tail]`
220280
opt_rest: ?struct {
281+
/// position in list of `..`; e.g. 0 in `[.., Foo, Bar]`
221282
offset: u16,
283+
/// e.g. tail in `..tail`
222284
name: ?Ident.Idx,
223285
},
224286
},
287+
/// _ is used as a catch-all, it matches anything
225288
underscore,
226289
compiler_bug: Problem.Compiler,
227-
/// todo
290+
/// List of Pattern
228291
pub const List = collections.SafeList(@This());
229-
/// todo
292+
/// Index into Pattern.List
230293
pub const Idx = List.Idx;
231-
/// todo
294+
/// Sublist reference of Pattern.List
232295
pub const Slice = List.Slice;
233-
/// todo
296+
/// Sublist reference into Pattern.List that is guaranteed to be non-empty
234297
pub const NonEmptySlice = List.NonEmptySlice;
235-
/// todo
298+
/// Pattern with accompanying type
236299
pub const Typed = struct {
237300
pattern: Pattern.Idx,
238301
type: Type.Idx,
239-
/// todo
302+
/// List of Pattern.Typed
240303
pub const List = collections.SafeMultiList(@This());
241-
/// todo
304+
/// Reference to sublist into Pattern.Typed.List
242305
pub const Slice = Typed.List.Slice;
243306
};
244307
};
245-
/// todo
308+
309+
/// Identifier along with its type
246310
pub const TypedIdent = struct {
311+
/// e.g. `x`
247312
pattern: Pattern.Idx,
248313
type: Type.Idx,
249-
/// todo
314+
/// List of TypedIdent
250315
pub const List = collections.SafeMultiList(@This());
251-
/// todo
316+
/// Reference to sublist into TypedIdent.List
252317
pub const Slice = List.Slice;
253318
};

0 commit comments

Comments
 (0)