File layout
A plugin is found by its folder, and the build checks that a plugin names only what it imports. Knowing where things live tells you what can see what.
The repository, as planned
The parts marked “exists” are on the branch core today: a build, a test library and the packaging, made before the design and proposed for reuse. The rest is what the plan adds. Tuna’s default plugins live in the same repository as the core, in their own folder.
tuna/
README.md the name and one sentence; nothing else
Makefile make build, make test, make repl, make exe, make clean (exists)
build.ss refuses any Chez but threaded 10.4.1; a compile warning fails the build (exists)
bin/tuna.sps the program's entry point (exists)
boot/ one executable with Chez inside (exists)
src/tuna/
main.sls command line: --version, and (planned) "tuna check" (exists, grows)
test.sls test, check, check-equal?, check-raises (exists)
plugin.sls (tuna plugin): the forms every plugin uses
build/ the plugin build: reads plugin.ss and contract.ss, expands, checks, generates
... the core proper: runs, receipts, tables, options, saved data, loop, workers
lib/
h2o/ the HTTP library (on its own branch)
(plain data) the persistent map, checks such as list-of, define-plain-record
plugins/
processes/ the process service, with its helper program
journal-store/ the storage plugin: writes saved data to disk
... every default plugin: buffers, keys, commands, modes, faces, minibuffer, web, ...
tests/ test plugins and the "workday" fixture
bench/ measurementsYour own files are apart from the repository: your init.ss, and any plugins of your own. Where they live on disk is not decided yet; Tuna is pointed at one or more plugin folders and finds each plugin by its folder’s name.
Emacs keeps the same split: Lisp files shipped with Emacs under lisp/, your init.el and packages under ~/.emacs.d/.
A plugin folder
terminal/
plugin.ss required: exactly one (plugin terminal ...) form
contract.ss optional: (contract (terminal) ...); if present, it is the interface
reader.ss optional: any file the plugin includes with (include "reader.ss")
README.md a brief note beside the pluginplugin.ssholds one form,(plugin NAME ...), shaped like Chez’slibraryform. The folder’s name andNAMEmust agree.contract.ss, if present, is the plugin’s interface:(contract (text-store) ...). Without it, the interface is the plugin’sexportlist, named after the plugin, as an OCaml module without an interface file exports everything it lists. If a plugin has both, it is reported andcontract.sswins. A contract meant to be implemented by other plugins should have acontract.ss, because only there can it declare saved data whole.- Included files split a long plugin, or hold code a plugin and its worker both need. A worker sees nothing of its plugin, so shared code must be included by both; each compiles its own copy.
- Other files are fine. The process service keeps
helper.ssbeside itsplugin.ssand finds it with(plugin-file "helper.ss").
An Emacs package is one or more .el files with (provide 'name) at the end; nothing separates its interface from its internals except the name--private naming convention.
What the build produces
make buildcompiles the core and libraries.make exemakesbuild/bin/tuna: one file with Chez inside, so running Tuna needs no Chez installation.- The plugin build runs inside Tuna, at start and at each reload. For each plugin it reads
plugin.ssandcontract.ss; expands every form with Chez’s own expander; reads from the expansion what each form defines, uses and assigns; checks everyc:xname against the imported contracts and everyimplementsagainst its contract, listing all mismatches in one message; compiles eachdefine-workeras a separate library; and makes one Chez library for the plugin that runs its forms in order. Results are cached by a hash of the source, so an unchanged plugin is not rebuilt. A reload of a one-line plugin took 1 to 5 ms in the prototype. tuna check(planned) checks yourinit.sswithout starting anything and lists every error with its line.
Emacs byte-compiles a file on request and warns about unknown functions; it does not refuse to load one. Tuna refuses at build, with the line, because a wrong name would otherwise fail only when that code runs.