diff --git a/hosts/ocaml/bin/sx_server.ml b/hosts/ocaml/bin/sx_server.ml index f82a0df4..3860b652 100644 --- a/hosts/ocaml/bin/sx_server.ml +++ b/hosts/ocaml/bin/sx_server.ml @@ -53,14 +53,10 @@ let rec serialize_value = function | Symbol s -> s | Keyword k -> ":" ^ k | List items | ListRef { contents = items } -> - (* Lists with a symbol head are call expressions: (fn arg1 arg2). - Lists starting with data values are data: (list 1 2 3). - This distinction matters for the client parser. *) - (match items with - | (Symbol _ | Keyword _) :: _ -> - "(" ^ String.concat " " (List.map serialize_value items) ^ ")" - | _ -> - "(list " ^ String.concat " " (List.map serialize_value items) ^ ")") + (* All lists: (items...) — no (list ...) wrapper. + Matches Python serialize() exactly. The SX source code itself uses + (list ...) where data lists are needed; the serializer preserves AST. *) + "(" ^ String.concat " " (List.map serialize_value items) ^ ")" | Dict d -> let pairs = Hashtbl.fold (fun k v acc -> (Printf.sprintf ":%s %s" k (serialize_value v)) :: acc) d [] in @@ -1635,7 +1631,8 @@ let read_css_file path = let http_inject_shell_statics env static_dir sx_sxc = (* Component definitions for client *) let buf = Buffer.create 65536 in - Hashtbl.iter (fun _sym v -> + Hashtbl.iter (fun sym v -> + let name = Sx_types.unintern sym in match v with | Component c -> let ps = String.concat " " ( @@ -1649,6 +1646,22 @@ let http_inject_shell_statics env static_dir sx_sxc = (if i.i_has_children then ["&rest"; "children"] else [])) in Buffer.add_string buf (Printf.sprintf "(defisland ~%s (%s) %s)\n" i.i_name ps (serialize_value i.i_body)) + | Lambda l when l.l_name <> None -> + (* Named lambdas — client needs utility functions like cssx-process-token *) + let fn_name = match l.l_name with Some n -> n | None -> name in + let ps = String.concat " " l.l_params in + Buffer.add_string buf (Printf.sprintf "(define %s (fn (%s) %s))\n" + fn_name ps (serialize_value l.l_body)) + | Macro m -> + let ps = String.concat " " m.m_params in + let mname = match m.m_name with Some n -> n | None -> name in + Buffer.add_string buf (Printf.sprintf "(defmacro %s (%s) %s)\n" + mname ps (serialize_value m.m_body)) + | Dict _ | Number _ | String _ | Bool _ | List _ | ListRef _ -> + (* Named values (dicts, lists, constants) — client needs CSSX config etc. *) + if String.length name > 0 && name.[0] <> '_' && name.[0] <> '*' then + Buffer.add_string buf (Printf.sprintf "(define %s %s)\n" + name (serialize_value v)) | _ -> () ) env.bindings; let raw_defs = Buffer.contents buf in