u u
zgomot, sguomot, harmalaie
--
intro.
this is an experiment in implementing a actor-based
runtime for producing midi event processors;
the language is lispy in nature, with an imperative feel;
the project is implemented in two parts --
1. a c shim for dealing with jack stuff and reading
user input, and
2. a lua interpreter and read-eval-print-loop
interface;
also, this project makes bad use of
https://github.com/antirez/linenoise
(BSD 2-Clause License)
by statically linking against a modified version of it.
compiling.
requires: lua and jack development headers;
$ make
this should have produced an executable named sguomot
at the root of the project.
running.
the executable takes a command-line argument which is
a lua package path description;
if running from the root of the repository, you need
to point it to where the lua parts exists:
$ ./sguomot 'src/lua/?/init.lua;src/lua/?.lua'
caveat: the init.lua script path is hardcoded.
examples.
check out the examples/ folder; the examples there
use most of the available features;
to run the debugger example:
1. start sguomot;
2. load the example with
(load "examples/debugger.sgmt");
3. (jack) connect a MIDI event source to the input
port of sguomot;
4. do something with that device so that it produces
events; the events should show up on screen.
quitting.
this software is really buggy -- worst case, it might
fail to properly start -- in that case you would need
to kill it;
the error handling is poorly done; any syntax or runtime
error will crash the scheduler, and at that point you
need to do ^C^D to close everything and start again.
notes on the language.
the c runtime initializes a jack client with two (i/o)
midi ports; the lua runtime reads events from a ring
buffer, and writes events to another ring buffer;
the dynamic symbol *main* represents the actor which
receives events from outside; if you get a periodic
"no *main*" message, that means the symbol is bound
to nothing;
builtin functions:
arithmetic: +, -
comparison: >, <, =, nil?, zero?
logic: not
actorstuff: send, spawn
debug: pr
builtin forms:
conditional:
(if *cond* *then* *else*)
(when *cond* *then*)
(cond *guard0* *body0* ... *guardN* *bodyN*)
looping:
(while *cond* *body* ...)
environment:
(set *name* *expr*)
(let [*name0* *expr0* ... *nameN* *exprN*] *body*)
sequencing:
(do *expr0* ... *exprN*)
actorstuff:
(recv *pattern0* *body0* ... *patternN* *bodyN*)
repl-level primitives:
(def *name* *expr*)
(actor *name* *args* *body*)
(spawn* *maker* *arg0* ... *argN*)
(send* *destination* *message*)
(load *filename*)