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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
(* SPDX-License-Identifier: AGPL-3.0-or-later *)
(* Copyright © 2021-2026 OCamlPro *)
(* Written by the Owi programmers *)

module Value = Abstract_value

type t = Value.t list

exception Empty

let empty = []

let push s v = v :: s

let push_bool s ctx b = push s (Value.I32 (Value.I32.of_boolean ctx b))

let push_concrete_i32 s ctx i = push s (Value.I32 (Value.I32.of_int32 ctx i))

let push_i32 s i = push s (Value.I32 i)

let push_i32_of_int s ctx i = push_concrete_i32 s ctx (Int32.of_int i)

let push_concrete_i64 s ctx i = push s (Value.I64 (Value.I64.of_int64 ctx i))

let push_i64 s i = push s (Value.I64 i)

let push_concrete_f32 s f = push s (Value.F32 (Value.F32.of_float32 f))

let push_f32 s f = push s (Value.F32 f)

let push_concrete_f64 s f =
  push s (Value.F64 (Value.F64.of_float (Float64.to_float f)))

let push_f64 s f = push s (Value.F64 f)

let push_concrete_v128 s f = push s (Value.V128 (Value.V128.of_concrete f))

let push_v128 s f = push s (Value.V128 f)

let push_ref s r = push s (Value.Ref r)

let push_array _ _ = assert false

let pp ctx fmt (s : t) =
  Fmt.list
    ~sep:(fun fmt () -> Fmt.string fmt " ; ")
    (Value.pp_with_ctx ctx) fmt s

let pop = function [] -> raise Empty | hd :: tl -> (hd, tl)

let drop = function [] -> raise Empty | _hd :: tl -> tl

let pop_i32 s =
  let hd, tl = pop s in
  match hd with Value.I32 n -> (n, tl) | _ -> assert false

let pop2_i32 s =
  let n2, s = pop s in
  let n1, tl = pop s in
  match (n1, n2) with
  | Value.I32 n1, I32 n2 -> ((n1, n2), tl)
  | _ -> assert false

let pop_i64 s =
  let hd, tl = pop s in
  match hd with Value.I64 n -> (n, tl) | _ -> assert false

let pop2_i64 s =
  let n2, s = pop s in
  let n1, tl = pop s in
  match (n1, n2) with
  | Value.I64 n1, I64 n2 -> ((n1, n2), tl)
  | _ -> assert false

let pop_f32 s =
  let hd, tl = pop s in
  match hd with Value.F32 f -> (f, tl) | _ -> assert false

let pop2_f32 s =
  let n2, s = pop s in
  let n1, tl = pop s in
  match (n1, n2) with
  | Value.F32 n1, F32 n2 -> ((n1, n2), tl)
  | _ -> assert false

let pop_f64 s =
  let hd, tl = pop s in
  match hd with Value.F64 f -> (f, tl) | _ -> assert false

let pop2_f64 s =
  let n2, s = pop s in
  let n1, tl = pop s in
  match (n1, n2) with
  | Value.F64 n1, F64 n2 -> ((n1, n2), tl)
  | _ -> assert false

let pop_v128 s =
  let hd, tl = pop s in
  match hd with Value.V128 f -> (f, tl) | _ -> assert false

let pop2_v128 s =
  let n2, s = pop s in
  let n1, tl = pop s in
  match (n1, n2) with
  | Value.V128 n1, V128 n2 -> ((n1, n2), tl)
  | _ -> assert false

let pop_ref s =
  let hd, tl = pop s in
  match hd with Value.Ref _ -> (hd, tl) | _ -> assert false

let pop_as_ref s =
  let hd, tl = pop s in
  match hd with Value.Ref hd -> (hd, tl) | _ -> assert false

let pop_bool s ctx =
  let hd, tl = pop s in
  match hd with
  | Value.I32 n -> (Value.I32.to_boolean ctx n, tl)
  | _ -> assert false

let pop_n s n =
  (List.filteri (fun i _hd -> i < n) s, List.filteri (fun i _hd -> i >= n) s)

let keep s n = List.filteri (fun i _hd -> i < n) s

let rec drop_n s n =
  if n = 0 then s
  else match s with [] -> assert false | _ :: tl -> drop_n tl (n - 1)

let apply_i32_boolean s ctx f =
  let hd, tl = pop_i32 s in
  push_bool tl ctx (f hd)

let apply_i32_i32 s f =
  let hd, tl = pop_i32 s in
  push_i32 tl (f hd)

let apply_i32_f32 s f =
  let hd, tl = pop_i32 s in
  push_f32 tl (f hd)

let apply_i32_f64 s f =
  let hd, tl = pop_i32 s in
  push_f64 tl (f hd)

let apply_i32_i64 s f =
  let hd, tl = pop_i32 s in
  push_i64 tl (f hd)

let apply_i32_i32_i32 s f =
  let (hd1, hd2), tl = pop2_i32 s in
  push_i32 tl (f hd1 hd2)

let apply_i32_i32_boolean s ctx f =
  let (hd1, hd2), tl = pop2_i32 s in
  push_bool tl ctx (f hd1 hd2)

let apply_i64_boolean s f =
  let hd, tl = pop_i64 s in
  push_bool tl (f hd)

let apply_i64_i64 s f =
  let hd, tl = pop_i64 s in
  push_i64 tl (f hd)

let apply_i64_i32 s f =
  let hd, tl = pop_i64 s in
  push_i32 tl (f hd)

let apply_i64_f32 s f =
  let hd, tl = pop_i64 s in
  push_f32 tl (f hd)

let apply_i64_f64 s f =
  let hd, tl = pop_i64 s in
  push_f64 tl (f hd)

let apply_i64_i64_i64 s f =
  let (hd1, hd2), tl = pop2_i64 s in
  push_i64 tl (f hd1 hd2)

let apply_i64_i64_boolean s ctx f =
  let (hd1, hd2), tl = pop2_i64 s in
  push_bool tl ctx (f hd1 hd2)

let apply_f32_f32 s f =
  let hd, tl = pop_f32 s in
  push_f32 tl (f hd)

let apply_f32_f64 s f =
  let hd, tl = pop_f32 s in
  push_f64 tl (f hd)

let apply_f32_i32 s f =
  let hd, tl = pop_f32 s in
  push_i32 tl (f hd)

let apply_f32_i64 s f =
  let hd, tl = pop_f32 s in
  push_i64 tl (f hd)

let apply_f32_f32_f32 s f =
  let (hd1, hd2), tl = pop2_f32 s in
  push_f32 tl (f hd1 hd2)

let apply_f32_f32_boolean s f =
  let (hd1, hd2), tl = pop2_f32 s in
  push_bool tl (f hd1 hd2)

let apply_f64_f64 s f =
  let hd, tl = pop_f64 s in
  push_f64 tl (f hd)

let apply_f64_f32 s f =
  let hd, tl = pop_f64 s in
  push_f32 tl (f hd)

let apply_f64_i32 s f =
  let hd, tl = pop_f64 s in
  push_i32 tl (f hd)

let apply_f64_i64 s f =
  let hd, tl = pop_f64 s in
  push_i64 tl (f hd)

let apply_f64_f64_f64 s f =
  let (hd1, hd2), tl = pop2_f64 s in
  push_f64 tl (f hd1 hd2)

let apply_f64_f64_boolean s f =
  let (hd1, hd2), tl = pop2_f64 s in
  push_bool tl (f hd1 hd2)