diff --git a/hosts/ocaml/bin/mcp_tree.ml b/hosts/ocaml/bin/mcp_tree.ml index 0d20799a..1ee4d348 100644 --- a/hosts/ocaml/bin/mcp_tree.ml +++ b/hosts/ocaml/bin/mcp_tree.ml @@ -198,6 +198,8 @@ let setup_env () = | _ -> Nil ) nodes path | _ -> Nil); + (* use — module declaration, no-op at eval time, metadata for static analysis *) + bind "use" (fun _args -> Nil); bind "trim" (fun args -> match args with | [String s] -> String (String.trim s) | _ -> String ""); bind "split" (fun args -> match args with @@ -1131,6 +1133,13 @@ let rec handle_tool name args = ) items with _ -> () ) all_sx_files; + (* Find use declarations *) + let use_decls = call_sx "find-use-declarations" [tree] in + let declared_modules = match use_decls with + | List items | ListRef { contents = items } -> + List.filter_map (fun v -> match v with String s -> Some s | _ -> None) items + | _ -> [] + in (* Format output *) let lines = List.map (fun sym -> if Hashtbl.mem file_defines sym then @@ -1145,8 +1154,11 @@ let rec handle_tool name args = | Some n -> Printf.sprintf "Dependencies of %s in %s" n file | None -> Printf.sprintf "Dependencies of %s" file in - text_result (Printf.sprintf "%s\n%d symbols referenced:\n%s" - header (List.length sym_names) (String.concat "\n" lines)) + let use_str = if declared_modules = [] then "" else + Printf.sprintf "\n\nDeclared modules (use):\n %s" (String.concat ", " declared_modules) + in + text_result (Printf.sprintf "%s\n%d symbols referenced:\n%s%s" + header (List.length sym_names) (String.concat "\n" lines) use_str) | "sx_build_manifest" -> let target = (try args |> member "target" |> to_string with _ -> "js") in diff --git a/lib/tree-tools.sx b/lib/tree-tools.sx index f758ca7f..12461d2d 100644 --- a/lib/tree-tools.sx +++ b/lib/tree-tools.sx @@ -1315,3 +1315,18 @@ (for-each (fn (child) (walk child bound)) args))))))))) (walk node (dict)) result))) + +(define find-use-declarations :effects () + (fn (nodes) + (let ((uses (list))) + (for-each (fn (node) + (when (and (list? node) (>= (len node) 2) + (= (type-of (first node)) "symbol") + (= (symbol-name (first node)) "use")) + (for-each (fn (arg) + (cond + (= (type-of arg) "symbol") (append! uses (symbol-name arg)) + (= (type-of arg) "string") (append! uses arg))) + (rest node)))) + (if (list? nodes) nodes (list nodes))) + uses)))