-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathgeneric_core_ty.ml
More file actions
161 lines (140 loc) · 5.27 KB
/
Copy pathgeneric_core_ty.ml
File metadata and controls
161 lines (140 loc) · 5.27 KB
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
(* * Generic_core_ty: Type witnesses.
In this module, we define the type =_ ty= reflecting type terms to value terms.
We call such terms /type codes/.
The GADT syntax allows us to constrain the type parameter of =_ ty= so that for any given
type parameter =t=, there is at most one value of type =t ty=, that value is the reflection of =t=.
For each type of arity =n=, corresponds a =ty= constructor of arity =n= whose arguments are themselves
=ty= values reflecting the type parameters.
*)
module T = struct
(* ** Type Reflection
=_ ty= is extensible: when the user defines a new type =('a0,...'an) t=,
we add a homonymous constructor to =_ty=:
: _ ty += T : 'a0 ty * ... * 'an ty -> ('a0,...'an) t ty
*)
type _ ty = ..
(* *** Primitive and Standard Types
The core generic library comes with the type reflection and introspection for all types in the standard library. Other types need to be added by the user, either manually or through dedicated PPX.
*)
type _ ty +=
| Any : 'a ty (* wildcard pattern *)
(* Base types *)
| Int32 : int32 ty
| Int64 : int64 ty
| Nativeint : nativeint ty
| Lazy : 'a ty -> 'a Lazy.t ty
| Exn : exn ty
| Bool : bool ty
| Int : int ty
| Float : float ty
| Char : char ty
| Bytes : bytes ty
| String : string ty
| Option : 'a ty -> 'a option ty
| List : 'a ty -> 'a list ty
| Array : 'a ty -> 'a array ty
| Ref : 'a ty -> 'a ref ty
| Ty : 'a ty -> 'a ty ty
| Unit : unit ty
| Pair : 'a ty * 'b ty -> ('a * 'b) ty
| Triple : 'a ty * 'b ty * 'c ty -> ('a * 'b * 'c) ty
| Quadruple : 'a ty * 'b ty * 'c ty * 'd ty -> ('a * 'b * 'c * 'd) ty
| Quintuple : 'a ty * 'b ty * 'c ty * 'd ty * 'e ty -> ('a * 'b * 'c * 'd * 'e) ty
| Sextuple : 'a ty * 'b ty * 'c ty * 'd ty * 'e ty * 'f ty -> ('a * 'b * 'c * 'd * 'e * 'f) ty
| Septuple : 'a ty * 'b ty * 'c ty * 'd ty * 'e ty * 'f ty * 'g ty -> ('a * 'b * 'c * 'd * 'e * 'f * 'g) ty
| Octuple : 'a ty * 'b ty * 'c ty * 'd ty * 'e ty * 'f ty * 'g ty * 'h ty -> ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h) ty
| Nonuple : 'a ty * 'b ty * 'c ty * 'd ty * 'e ty * 'f ty * 'g ty * 'h ty * 'i ty -> ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h * 'i) ty
| Decuple : 'a ty * 'b ty * 'c ty * 'd ty * 'e ty * 'f ty * 'g ty * 'h ty * 'i ty * 'j ty -> ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h * 'i * 'j) ty
| Fun : 'a ty * 'b ty -> ('a -> 'b) ty
end
include T
type 'a t = 'a ty
(* ** Forgetting the index
The GADT syntax allows us to forget the type index using existential quantification.
The type =ty'= is the union of all ='a ty= for all ='a=.
TODO: rename ty' to typename
*)
type ty' = E : 'a ty -> ty'
(* *** Equality on types of possibly different indices
Using the index-less =ty'= we may now compare ='a ty= and ='b ty= values
using the generic equality primitive.
*)
let eq x y = try E x = E y with _ -> false
let neq x y = not (eq x y)
(* ** Helping functions
=with_type= is used to help the type-checker fix the type of a value to the index of ='a ty=.
*)
let with_type : 'a ty -> 'a -> 'a
= fun _ x -> x
(* ** Type Patterns
*)
type 'a pat = 'a ty (* used in a context where Any is allowed *)
(* *** Wildcard pattern
The constructor =Any= is a type pattern that can match any type.
It is not valid in contexts where a type code is expected: use only in contexts where a pattern is expected.
*)
let any = Any
(* *** Some Patterns
*)
let pair = T.Pair (Any, Any)
let triple = T.Triple (Any,Any,Any)
let quadruple = T.Quadruple (Any,Any,Any,Any)
let quintuple = T.Quintuple (Any,Any,Any,Any,Any)
let sextuple = T.Sextuple (Any,Any,Any,Any,Any,Any)
let septuple = T.Septuple (Any,Any,Any,Any,Any,Any,Any)
let octuple = T.Octuple (Any,Any,Any,Any,Any,Any,Any,Any)
let nonuple = T.Nonuple (Any,Any,Any,Any,Any,Any,Any,Any,Any)
let decuple = T.Decuple (Any,Any,Any,Any,Any,Any,Any,Any,Any,Any)
let option = T.Option Any
let list = T.List Any
let array = T.Array Any
(* *** Constructor pattern
=conpat= computes the constructor pattern of a type code:
it replaces all the parameters with =Any=.
It uses the =Obj= representation to directly manipulate the
memory representation.
It generalises of the following cases:
: let conpat : type a . a ty -> a ty =
: function
: | Int -> Int
: | List t -> List Any
: | Pair (a,b) -> Pair (Any, Any)
*)
let conpat : 'a ty -> 'a ty =
fun value ->
let open Obj in
let rv = repr value in
tag rv |>
function
| t when t == object_tag
(* [value] is a constructor of arity 0 *)
-> value
| t when t == 0
(* [value] has a constructor [field rv 0] of arity [size rv - 1] *)
-> let any = repr Any
and n = size rv in
let con = new_block t n in
begin
set_field con 0 (field rv 0);
for i = 1 to n - 1 do
set_field con i any
done;
obj con
end
| _ -> assert false
;;
(* =conpat'= is the =ty'= version of =conpat=, working on index-less type codes *)
let conpat' (E t) = E (conpat t)
(* * Dynamic values
*)
module Typed = struct
type 'a typed = 'a ty * 'a
end
include Typed
type _ ty += Typed : 'a ty -> 'a typed ty
module Dynamic = struct
type dynamic = Dyn : 'a typed -> dynamic
type dyn = dynamic
end
include Dynamic
type _ ty += Dynamic : dynamic ty