-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvalueops.ml
194 lines (158 loc) · 5.84 KB
/
valueops.ml
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
(*
* Copyright (c) 2017-2018, Artem Shinkarov <[email protected]>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*)
open Ast
open Value
open Ordinals
open Print
open Printf
(** Predicates. **)
let value_is_true v =
match v with
| VTrue -> true
| _ -> false
let value_is_false v =
match v with
| VFalse -> true
| _ -> false
let value_is_num v =
match v with
| VNum (o) -> true
| _ -> false
let value_is_array v =
match v with
| VArray (_, _) -> true
| _ -> false
let value_is_closure v =
match v with
| VClosure (_, _) -> true
| _ -> false
let value_is_imap v =
match v with
| VImap (_, _, _, _) -> true
| _ -> false
let value_is_filter v =
match v with
| VFilter (_, _, _) -> true
| _ -> false
let value_is_selectable v =
match v with
(* Constants with shape [] can be selected at index []. *)
| VTrue
| VFalse
| VNum (_)
(* Array, imap, filter. *)
| VArray (_, _)
| VImap (_, _, _, _)
| VFilter (_, _, _) -> true
| _ -> false
(** Constructors **)
let mk_false_value = VFalse
let mk_true_value = VTrue
let mk_int_value n = VNum (int_to_ord n)
let mk_ord_value o = VNum (o)
let mk_array_value shp_vec data_vec =
if not @@ List.for_all (fun x -> value_is_num x) shp_vec then
value_err @@ sprintf "mk_array: invalid shape vector [%s]"
@@ val_lst_to_str shp_vec;
let elcount = List.fold_left (fun res x ->
match x with
| VNum o -> mult res o
| _ -> failwith "non-number found in shape")
one shp_vec in
if compare elcount omega <> -1 then
value_err @@ sprintf "mk_array: shape [%s] suggests that arrray will have more than omega elements"
@@ val_lst_to_str shp_vec;
if ord_to_nat elcount <> List.length data_vec then
value_err @@ sprintf "mk_array: shape [%s] does not match data [%s]"
(val_lst_to_str shp_vec) (val_lst_to_str data_vec);
if shp_vec = [] then
List.hd data_vec
else
VArray (shp_vec, data_vec)
let mk_closure_value e env =
if not @@ expr_is_lambda e then
value_err @@ sprintf "mk_closure: expected abstraction as first argument, got `%s'"
@@ expr_to_str e;
VClosure (e, env)
let mk_empty_vector () = VArray ([mk_int_value 0], [])
let mk_vector value_vec =
VArray ([mk_int_value @@ List.length value_vec], value_vec)
let mk_imap_value p1 p2 parts env =
(* XXX not sure we need to check that partitions are sane as it is
quite expensive. *)
VImap (p1, p2, parts, env)
let mk_filter_value p1 p2 parts =
VFilter (p1, p2, parts)
let value_num_to_ord v =
match v with
| VNum o -> o
| _ -> value_err @@ sprintf "value_num_to ord called with `%s'" @@ value_to_str v
let value_num_add v1 v2 =
VNum (add (value_num_to_ord v1) (value_num_to_ord v2))
let value_num_mult v1 v2 =
VNum (mult (value_num_to_ord v1) (value_num_to_ord v2))
(* This function returns an integer. *)
let value_num_compare v1 v2 =
compare (value_num_to_ord v1) (value_num_to_ord v2)
let value_array_to_pair v =
match v with
| VArray (s, d) -> (s, d)
| _ -> value_err @@ sprintf "value_array_to_pair called with `%s'" @@ value_to_str v
let value_imap_to_tuple v =
match v with
| VImap (p1, p2, parts, env) -> (p1, p2, parts, env)
| _ -> value_err "value_imap_to_tuple"
let value_filter_to_tuple v =
match v with
| VFilter (p1, p2, parts) -> (p1, p2, parts)
| _ -> value_err "value_filter_to_tuple"
let value_num_vec_lt l r =
List.fold_left2 (fun r x y ->
if not r then
r
else
value_num_compare x y = -1)
true
l r
let value_num_vec_le l r =
List.fold_left2 (fun r x y ->
if not r then
r
else
let cmp = value_num_compare x y in
cmp = -1 || cmp = 0)
true
l r
let value_num_vec_in_vgen vec vgen =
let lb, x, ub = vgen in
let _, lb_data_vec = value_array_to_pair lb in
let _, ub_data_vec = value_array_to_pair ub in
value_num_vec_le lb_data_vec vec && value_num_vec_lt vec ub_data_vec
let value_closure_to_triple v =
match v with
| VClosure ({ expr_kind = ELambda (x, body) }, env) ->
(x, body, env)
| _ ->
value_err @@ sprintf "expected closure with abstraction, but got `%s' instead"
@@ value_to_str v
let value_imap_is_finite st v =
match v with
| VImap (p1, p2, _, _) ->
let _, outer_shape_vec = value_array_to_pair @@ Storage.st_lookup st p1 in
let _, inner_shape_vec = value_array_to_pair @@ Storage.st_lookup st p2 in
List.for_all (fun x -> (value_num_compare x (VNum omega)) = -1)
(List.append outer_shape_vec inner_shape_vec)
| _ -> value_err "value_imap_is_finite"