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:
@@ -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
|
||||
|
||||
(* ====================================================================== *)
|
||||
|
||||
@@ -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)))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user