Fix serialize_value for SxExpr/Spread; handle List-of-SxExpr in aser output

serialize_value was falling through to "nil" for SxExpr and Spread values.
Now SxExpr passes through as raw SX text, Spread serializes as make-spread.

The aser command's result handler now joins a List of SxExprs as a
space-separated fragment (from map/filter producing multiple SxExprs).

Investigation ongoing: handler aser responses still have "class" strings
where :class keywords should be — the component expansion path in aser
loses keyword types during CEK evaluation of component bodies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-24 18:16:33 +00:00
parent c8280e156f
commit 33af6b9266

View File

@@ -59,6 +59,11 @@ let rec serialize_value = function
(Printf.sprintf ":%s %s" k (serialize_value v)) :: acc) d [] in
"{" ^ String.concat " " pairs ^ "}"
| RawHTML s -> "\"" ^ escape_sx_string s ^ "\""
| SxExpr s -> s
| Spread pairs ->
let items = List.map (fun (k, v) ->
Printf.sprintf ":%s %s" k (serialize_value v)) pairs in
"(make-spread {" ^ String.concat " " items ^ "})"
| _ -> "nil"
(** Request epoch — monotonically increasing, set by (epoch N) from Python.
@@ -822,6 +827,15 @@ let rec dispatch env cmd =
Use (ok-raw ...) so Python knows not to unescape. *)
(match result with
| String s | SxExpr s -> send_ok_raw s
| List items | ListRef { contents = items } ->
(* List of SxExprs from map/filter — join them as a fragment *)
let parts = List.filter_map (fun v -> match v with
| SxExpr s -> Some s
| String s -> Some ("\"" ^ escape_sx_string s ^ "\"")
| Nil -> None
| v -> Some (serialize_value v)) items in
if parts = [] then send_ok_raw ""
else send_ok_raw (String.concat " " parts)
| _ -> send_ok_value result)
with
| Eval_error msg -> send_error msg