src/Pure/System/scala.ML
author wenzelm
Mon, 29 Aug 2022 19:26:27 +0200
changeset 76019 f3d8da992445
parent 75577 c51e1cef1eae
child 78675 f0a4ad78c0f2
permissions -rw-r--r--
provide cvc5-1.0.2 (inactive);

(*  Title:      Pure/System/scala.ML
    Author:     Makarius

Invoke Scala functions from the ML runtime.
*)

signature SCALA =
sig
  exception Null
  val function_bytes: string -> Bytes.T list -> Bytes.T list
  val function1_bytes: string -> Bytes.T -> Bytes.T
  val function: string -> string list -> string list
  val function1: string -> string -> string
end;

structure Scala: SCALA =
struct

exception Null;

local

val new_id = string_of_int o Counter.make ();

val results =
  Synchronized.var "Scala.results" (Symtab.empty: Bytes.T list Exn.result Symtab.table);

val _ =
  Protocol_Command.define_bytes "Scala.result"
    (fn id :: tag :: rest =>
      let
        val result =
          (case (Bytes.content tag, rest) of
            ("0", []) => Exn.Exn Null
          | ("1", _) => Exn.Res rest
          | ("2", [msg]) => Exn.Exn (ERROR (Bytes.content msg))
          | ("3", [msg]) => Exn.Exn (Fail (Bytes.content msg))
          | ("4", []) => Exn.Exn Exn.Interrupt
          | _ => raise Fail "Malformed Scala.result");
      in Synchronized.change results (Symtab.map_entry (Bytes.content id) (K result)) end);

in

fun function_bytes name args =
  Thread_Attributes.uninterruptible (fn restore_attributes => fn () =>
    let
      val id = new_id ();
      fun invoke () =
       (Synchronized.change results (Symtab.update (id, Exn.Exn Match));
        Output.protocol_message (Markup.invoke_scala name id) (map Bytes.contents_blob args));
      fun cancel () =
       (Synchronized.change results (Symtab.delete_safe id);
        Output.protocol_message (Markup.cancel_scala id) []);
      fun await_result () =
        Synchronized.guarded_access results
          (fn tab =>
            (case Symtab.lookup tab id of
              SOME (Exn.Exn Match) => NONE
            | SOME result => SOME (result, Symtab.delete id tab)
            | NONE => SOME (Exn.Exn Exn.Interrupt, tab)));
    in
      invoke ();
      Exn.release (restore_attributes await_result ())
        handle exn => (if Exn.is_interrupt exn then cancel () else (); Exn.reraise exn)
    end) ();

val function1_bytes = singleton o function_bytes;

fun function name = map Bytes.string #> function_bytes name #> map Bytes.content;

val function1 = singleton o function;

end;

end;