Skip to content

Commit 6a30b0a

Browse files
committed
comments and changelog
1 parent 7116064 commit 6a30b0a

File tree

4 files changed

+40
-6
lines changed

4 files changed

+40
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
- Use FORCE_COLOR environmental variable to force colorized output https://github.com/rescript-lang/rescript-compiler/pull/7033
2222
- Allow spreads of variants in patterns (`| ...someVariant as v => `) when the variant spread is a subtype of the variant matched on. https://github.com/rescript-lang/rescript-compiler/pull/6721
23+
- Allow pattern matching on dicts. `switch someDict { | dict{"one": 1} => Js.log("one is one") }` https://github.com/rescript-lang/rescript-compiler/pull/7059
2324

2425
#### :bug: Bug fix
2526

jscomp/ml/dict_type_helpers.ml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,33 @@
1+
(*
2+
An overview of the implementation of dicts in ReScript:
3+
### What is a dict?
4+
Dicts are effectively an object with unknown fields, but a single known type of the values it holds.
5+
6+
### How are they implemented?
7+
Dicts in ReScript are implemented as predefined record type, with a single (magic) field that holds
8+
the type of the dict's values. This field is called `dictValuesType`, and is just an implementation
9+
detail - it's never actually exposed to the user, just used internally.
10+
11+
The compiler will route any label lookup on the dict record type to the magic field, which creates a
12+
record with unknown keys, but of a single type.
13+
14+
The reason for this seemingly convoluted implementation is that it allows us to piggyback on the
15+
existing record pattern matching mechanism, which means we get pattern matching on dicts for free.
16+
17+
### Modifications to the type checker
18+
We've made a few smaller modifications to the type checker to support this implementation:
19+
20+
- We've added a new predefined type `dict` that is a record with a single field called `dictValuesType`.
21+
This type is used to represent the type of the values in a dict.
22+
- We've modified the type checker to recognize `dict` patterns, and route them to the predefined `dict` type.
23+
This allows us to get full inference for dicts in patterns.
24+
25+
### Syntax
26+
There's first class syntax support for dicts, both as expressions and as patterns.
27+
A dict pattern is treated as a record pattern in the compiler and syntax, with an attriubute `@res.dictPattern`
28+
attached to it. This attribute is used to tell the compiler that the pattern is a dict pattern, and is what
29+
triggers the compiler to treat the dict record type differently to regular record types.
30+
*)
131
let dict_magic_field_name = "dictValuesType"
232

333
let has_dict_pattern_attribute attrs =

jscomp/ml/predef.ml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,14 @@ let common_initial_env add_type add_extension empty_env =
220220
type_variance = [Variance.covariant; Variance.covariant]}
221221
and decl_dict =
222222
let tvar = newgenvar() in
223-
(* Dicts are implented as a as a single "magic" field record. This magic field
224-
is then leveraged to be able to piggy back on the existing record pattern
225-
matching mechanism. So, this definition is import for the dict pattern
226-
matching functionality, but not something intended to be exposed to the
227-
user. *)
223+
(* Dicts are implemented as a single "magic" field record. This magic field
224+
is the medium through which we can piggy back on the existing record pattern
225+
matching mechanism. We do this by letting the compiler route any label lookup
226+
for the dict record type to the magic field, which has the type of the values
227+
of the dict.
228+
229+
So, this definition is important for the dict pattern matching functionality,
230+
but not something intended to be exposed to the user. *)
228231
{decl_abstr with
229232
type_attributes = [Dict_type_helpers.dict_attr];
230233
type_params = [tvar];

jscomp/ml/typecore.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ end) = struct
806806
Env.mark_type_used env (Path.last tpath) (Env.find_type tpath env);
807807
let is_dict = Path.same tpath Predef.path_dict in
808808
if is_dict then (
809-
(* [dict] Dicts are implented as a record with a single "magic" field. This magic field is
809+
(* [dict] Dicts are implemented as a record with a single "magic" field. This magic field is
810810
used to track the dict value type, and any label lookup on the dict record type
811811
will give that single value type back. This is how we can piggy back on the record
812812
pattern matching mechanism.

0 commit comments

Comments
 (0)