The piece between an editor and everything else. One long-lived Session, the program it belongs to launched and owned by the same process, and a socket that takes forms and installs them. What it adds over flan reload is that the session persists - a defvar added by one evaluation is part of what the next is checked against - and that it owns the build, which is what makes its layout rules describe the process actually running rather than a guess about it. The protocol is s-expressions rather than bencode, and I changed my mind about that. The case for nREPL was reusing a designed op set and not re-litigating session identity, but with the client ours too there is no CIDER to be compatible with, its eval is string-in/string-out with no slot for which form from which file, and Emacs already has read and prin1. So: one sexp per message, length framed because the payload contains newlines. No parsing code on the editor side, and on this side the parser is the language's own reader, where :op is already a keyword and Flan source is already a string literal. An nREPL front end can sit on the same Session later; it should not gate the editor. Two silent failures the daemon refuses to have. The agent socket is chosen by the daemon and forced through FLAN_AGENT_SOCKET before spawning, because a program's source has to name some path and a daemon that guessed would compile, build and deliver a module to nobody. And delivery is checked: agent/start returning 0 means a socket was bound, not that anyone connected, so a failed connect or a reply that is not ok becomes an error the editor sees. It waits for the program to bind before accepting an evaluation, since one arriving first fails for a reason that reads like a compiler bug, and it accepts with a timeout so a program that has exited takes the daemon with it instead of leaving an editor waiting on a socket nobody serves.
Description
Languages
OCaml
67.2%
Emacs Lisp
15.2%
C
10.4%
HTML
2.9%
Standard ML
2.8%
Other
1.5%