spec: promises — delay/force/delay-force/make-promise/promise?

25 tests pass on OCaml (4357 total) and JS. Promise represented as
mutable dict {:_promise true :forced :thunk :value}; delay-force
adds :_iterative for chain-following semantics.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 08:21:45 +00:00
parent 835b5314ce
commit e44cb89ab4
5 changed files with 306 additions and 3 deletions

View File

@@ -1141,6 +1141,26 @@ let make_test_env () =
Sx_ref.cek_call consumer (List spread)
| _ -> raise (Eval_error "call-with-values: expected 2 args"));
bind "promise?" (fun args ->
match args with
| [v] -> Bool (Sx_ref.is_promise v)
| _ -> Bool false);
bind "make-promise" (fun args ->
match args with
| [v] ->
let d = Hashtbl.create 4 in
Hashtbl.replace d "_promise" (Bool true);
Hashtbl.replace d "forced" (Bool true);
Hashtbl.replace d "value" v;
Dict d
| _ -> Nil);
bind "force" (fun args ->
match args with
| [p] -> Sx_ref.force_promise p
| _ -> Nil);
env
(* ====================================================================== *)

View File

@@ -1161,4 +1161,59 @@ let () = ignore (register_special_form (String "define-values")
| [args; env] -> sf_define_values args env
| _ -> Nil)))
(* Phase 9: Promises — delay/force/delay-force/make-promise/promise? *)
let make_promise_dict ?(iterative=false) thunk =
let d = Hashtbl.create 4 in
Hashtbl.replace d "_promise" (Bool true);
Hashtbl.replace d "forced" (Bool false);
Hashtbl.replace d "thunk" thunk;
Hashtbl.replace d "value" Nil;
if iterative then Hashtbl.replace d "_iterative" (Bool true);
Dict d
let sf_delay args env_val =
let expr = match args with List (e :: _) -> e | _ -> Nil in
let thunk = make_lambda (List []) expr env_val in
make_promise_dict thunk
let sf_delay_force args env_val =
let expr = match args with List (e :: _) -> e | _ -> Nil in
let thunk = make_lambda (List []) expr env_val in
make_promise_dict ~iterative:true thunk
let is_promise v =
match v with
| Dict d -> (match Hashtbl.find_opt d "_promise" with Some (Bool true) -> true | _ -> false)
| _ -> false
let rec force_promise p =
if not (is_promise p) then p
else match p with
| Dict d ->
(match Hashtbl.find_opt d "forced" with
| Some (Bool true) ->
(match Hashtbl.find_opt d "value" with Some v -> v | None -> Nil)
| _ ->
let thunk = (match Hashtbl.find_opt d "thunk" with Some t -> t | None -> Nil) in
let result = cek_call thunk (List []) in
let iterative = (match Hashtbl.find_opt d "_iterative" with Some (Bool true) -> true | _ -> false) in
let final_val = if iterative && is_promise result then force_promise result else result in
Hashtbl.replace d "forced" (Bool true);
Hashtbl.replace d "value" final_val;
final_val)
| _ -> p
let () = ignore (register_special_form (String "delay")
(NativeFn ("delay", fun call_args ->
match call_args with
| [args; env] -> sf_delay args env
| _ -> Nil)))
let () = ignore (register_special_form (String "delay-force")
(NativeFn ("delay-force", fun call_args ->
match call_args with
| [args; env] -> sf_delay_force args env
| _ -> Nil)))