anchor.diff:            { qid = q.qid; qq = GenericError "Current module unset" }
           | _ -> q
   
  +let validate_and_run_query st query =
  +  run_query st (validate_query st query).qq
  +
   (** This is the body of the JavaScript port's main loop. **)
  -let single_repl_iteration js_query st =
  -  let query = safe_unpack_interactive_query js_query |> validate_query st in
  -  let (status, response), state_opt = run_query st query.qq in
  +let js_repl_eval st query =
  +  let (status, response), st_opt = validate_and_run_query st query in
     let js_response = json_of_response query.qid status response in
  -  js_response, state_opt
  +  js_response, st_opt
  +
  +let js_repl_eval_js st query_js =
  +  js_repl_eval st (deserialize_interactive_query query_js)
  +
  +let js_repl_eval_str st query_str =
  +  let js_response, st_opt =
  +    js_repl_eval st (parse_interactive_query query_str) in
  +  (Util.string_of_json js_response), st_opt
  +
  +(** This too is called from FStar.js **)
  +let js_repl_init_opts () =
  +  let res, fnames = Options.parse_cmd_line () in
  +  match fnames with
  +  | _ :: _ -> failwith "repl_init: Unexpected: file names in option list"
  +  | [] ->
  +     match res with
  +     | Getopt.Help -> failwith "repl_init: --help unexpected"
  +     | Getopt.Error msg -> failwith ("repl_init: " ^ msg)
  +     | Getopt.Success -> () (* FIXME could do more validation here *)
   
   (** This is the main loop for the desktop version **)
   let rec go st : int =
  -  let query = read_interactive_query st.repl_stdin |> validate_query st in
  -  let (status, response), state_opt = run_query st query.qq in
  +  let query = read_interactive_query st.repl_stdin in
  +  let (status, response), state_opt = validate_and_run_query st query in
     write_response query.qid status response;
     match state_opt with
     | Inl st' -> go st'
  
positive.code:              ("level", JsonStr level);
               ("contents", js_contents)]
  
  let write_message level contents =
    write_json (json_of_message level contents)
  
  let json_of_hello =
    let js_version = JsonInt interactive_protocol_vernum in
  
negative.code:   | InvalidQuery msg -> { qid = qid; qq = ProtocolViolation msg }
    | UnexpectedJsonType (expected, got) -> wrap_js_failure qid expected got
  
  let deserialize_interactive_query js_query =
    try
      unpack_interactive_query js_query
    with
    | InvalidQuery msg -> { qid = "?"; qq = ProtocolViolation msg }
    | UnexpectedJsonType (expected, got) -> wrap_js_failure "?" expected got
  
  let parse_interactive_query query_str : query =
    match Util.json_of_string query_str with
    | None -> { qid = "?"; qq = ProtocolViolation "Json parsing failed." }
    | Some request -> deserialize_interactive_query request
  
  let read_interactive_query stream : query =
    match Util.read_line stream with
    | None -> exit 0
    | Some line -> parse_interactive_query line
  
  let json_of_opt json_of_a opt_a =
    Util.dflt JsonNull (Util.map_option json_of_a opt_a)
  