Skip to content

Commit bbdc397

Browse files
authored
Extend ocaml.ml (#10)
* Implement Sys.command * Start to add Bytes module Mostly corresponds to CakeML's Word8Array. * Add Array.length
1 parent 7b470ac commit bbdc397

2 files changed

Lines changed: 55 additions & 6 deletions

File tree

candle/basis_ffi.c.patch

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
--- basis_ffi.c
22
+++ basis_ffi.c
3-
@@ -294,6 +294,13 @@
3+
@@ -294,8 +294,34 @@
44
}
5-
5+
66
void fficustom (unsigned char *c, long clen, unsigned char *a, long alen) {
77
- assert(0 <= alen);
88
- assert(0 <= clen);
@@ -12,9 +12,28 @@
1212
+ } else if (strcmp(c, "getcwd") == 0) {
1313
+ assert(1 <= alen);
1414
+ a[0] = getcwd(a + 1, alen - 1) == NULL;
15-
+ } else {
15+
+ } else if (strcmp(c, "system") == 0) {
16+
+ assert(2 <= alen);
17+
+ assert(memchr(a, 0, alen) != NULL);
18+
+ int ret = system((const char *)a);
19+
+
20+
+ // return convention:
21+
+ // 0 < a[0] ==> no termination status for child
22+
+ // a[0] = 0 ==> a[1] = termination status of child
23+
+ if (ret == -1) {
24+
+ a[0] = 1;
25+
+ return;
26+
+ }
27+
+ if (!(WIFEXITED(ret))) {
28+
+ a[0] = 2;
29+
+ return;
30+
+ }
31+
+ a[0] = 0;
32+
+ a[1] = WEXITSTATUS(ret);
1633
+ return;
34+
+ } else {
35+
+ return; // Ignore unknown command
1736
+ }
1837
}
19-
38+
2039
// ---------------------------------------------------------------------------

candle/ocaml.ml

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ end;;
6262
module Int = struct
6363
let compare x y =
6464
if x < y then -1 else if x > y then 1 else 0
65+
let max x y = if x > y then x else y
6566
let to_string x = Cake.Int.toString x
6667
end;;
6768

@@ -169,6 +170,7 @@ end;;
169170

170171
module Array = struct
171172
let make n x = Cake.Array.array n x
173+
let length a = Cake.Array.length a
172174
let set a n x = try Cake.Array.update a n x
173175
with Subscript -> raise (Invalid_argument "Array.set")
174176
let get a n = try Cake.Array.sub a n
@@ -263,11 +265,39 @@ module Hashtbl = struct
263265
Cake.List.foldl (fun (x,y) acc -> f x y acc) init (Cake.Hashtable.toAscList tbl)
264266
end;;
265267

268+
module Bytes = struct
269+
let length s = Cake.Word8_array.length s
270+
(* NOTE OCaml also raises Invalid_argument if n > Sys.max_string_length;
271+
additionally, OCaml returns an uninitialized sequence with
272+
arbitrary bytes. *)
273+
let create n =
274+
if n < 0 then invalid_arg "Bytes.create: negative argument" else
275+
Cake.Word8_array.array n (Cake.Word8.fromInt 0)
276+
(* NOTE OCaml can raise Invalid_argument in get, set, blit_string.
277+
Unsure how the CakeML handle out-of-bounds accesses. *)
278+
let get s n = Cake.Word8_array.sub s n
279+
let set s n c = Cake.Word8_array.update s n c
280+
let blit_string src src_pos dst dst_pos len =
281+
Cake.Word8_array.copyVec src src_pos len dst dst_pos
282+
let to_string s = Cake.Word8_array.substring s 0 (length s)
283+
end;;
284+
266285
module Sys = struct
267286
let remove (s: string) = print "TODO Sys.remove (noop)\n"
268287
let command (s: string) =
269-
print_endline "TODO Sys.command (noop, always returns 1)";
270-
1
288+
let slen = String.length s in
289+
(* slen + 1: null-terminated string; 2: status bytes *)
290+
let blen = Int.max 2 (slen + 1) in
291+
let bytes = Bytes.create blen in
292+
(* Avoid recomputing length by using blit_string instead of of_string *)
293+
let _ = Bytes.blit_string s 0 bytes 0 slen in
294+
let _ = Cake.Runtime.customFFI "system" bytes in
295+
let ret = Cake.Word8.toInt (Bytes.get bytes 0) in
296+
let _ =
297+
if 0 < ret
298+
then raise (Sys_error "Sys.command: no termination status for child")
299+
else () in
300+
Cake.Word8.toInt (Bytes.get bytes 1);;
271301
let time () =
272302
print_endline "TODO Sys.time (always returns 0)";
273303
Float.zero;;

0 commit comments

Comments
 (0)