;;;; The dev agent, as Flan sees it. Three calls, and the shape of them is the ;;;; design: loading a redefinition and installing it are separate, because ;;;; only the program knows when it is between frames. ;;;; ;;;; (agent/start) listen somewhere sensible; once, at startup ;;;; (agent/start path) listen on that unix socket instead ;;;; (agent/poll) install whatever has arrived; returns how many ;;;; (agent/wait ms) the same, but waits for something first ;;;; ;;;; A game loop calls poll at the top of the frame and ignores the result. ;;;; wait is for a headless test, where waiting is what makes a reload ;;;; deterministic rather than a race against the frame rate. ;;;; ;;;; The path was the ceremony. Under [flan dev] the daemon has already decided ;;;; where it wants to talk to the program and says so in FLAN_AGENT_SOCKET, so ;;;; whatever the source named was being overridden anyway; outside the daemon ;;;; any path will do as long as the program says which one it picked. So the ;;;; argument is now optional, and the zero-argument form is the one to write. ;;;; The explicit form stays for a program that wants to choose — a fixed path ;;;; something else is already configured to connect to. ;;;; ;;;; No aggregate crosses this boundary, so there is no shim: a Flan string is ;;;; already ptr+len and flan_agent_start takes it that way. (declare start-at-raw [path string] i32 "flan_agent_start") (declare start-auto-raw [] i32 "flan_agent_start_auto") (declare poll-raw [] i32 "flan_agent_poll") (declare wait-raw [ms i32] i32 "flan_agent_wait") ;;; Both answer 0 for "listening" and -1 for "could not". Starting twice is not ;;; an error and not a second listener: the C side answers 0 and leaves the ;;; first socket alone, so a program that gets a listener from somewhere else ;;; and also calls start is a program with one listener. (defn start-at [path string] i32 (start-at-raw path)) (defn start-auto [] i32 (start-auto-raw)) ;;; The optional argument, which Flan has no other spelling for: a function ;;; takes the arity it declares, so the choice between the two above is made ;;; before the checker ever sees a call. Extra arguments are not silently ;;; dropped — they are spliced into [start-at], which then refuses them by its ;;; own arity, at the call site, in the usual words. (defmacro start [& args] (if (= (len args) 0) `(start-auto) `(start-at ~@args))) (defn poll [] i32 (poll-raw)) (defn wait [ms i32] i32 (wait-raw ms))