Open yaxu opened 3 years ago
turning tidal-listener into a multi-function tidal engine
sounds like a good idea!
We could distribute a ghci drop-in replacement. @jwaldmann already made this: https://github.com/jwaldmann/safe-tidal-cli . It looks good and is safe for exposing to untrusted users (e.g via flok), although doesn't support definitions with
let
.
On feedforward I implemented a way to interpret haskell code thorough hint
, and it supports let
for sure, not sure about the other constructs. This functions gets tidal code and evaluate it, I use(d) it to load shortcuts into the interpreter, don't know if it can be usable in the tidal-listener context
https://github.com/yaxu/feedforward/blob/master/src/TidalHint.hs#L68
A note on this - currently tidal-listener restarts the interpreter when an exception is raised. I'm not sure when this happens, it shouldn't on a type error as the typeChecksWithDetails
call should detect that before the code is interpreted. If/when it does happen though, any definitions would be lost.
Well I guess if it type checks, there shouldn't be a problem with interpreting the code.
Well I guess if it type checks, there shouldn't be a problem with interpreting the code.
As far as I know it does a lazy type-check. So in an expression like s "bd sn*"
it would type check it to ControlPattern
, even though the parser will fail to parse the expression and raise an exception.
Ah yes I see. If I do this:
import Sound.OSC.FD as O
udp <- udpServer "127.0.0.1" 6012
r <- openUDP "127.0.0.1" 6011
sendMessage r $ Message "/code" [string "hello", string "sound \"bd sn*\""]
The interpreter thread doesn't crash, but the whole of tidal-listener does! So the exception isn't raised in the interpreter (good) but later, when the parsec parser is invoked on the mininotation. So we want some exception handling elsewhere, probably similar to how Sound.Tidal.Stream works, where it catches an exception it returns to the previous pattern.
We should also try to make things as strict as possible so we can catch these errors before updating the pattern state. Just forcing the first cycle to be calculated would be fine.
Or we could probably do something fancy with template haskell, so that the parsec parsing is done during typechecking.
Ah yes I see. If I do this:
import Sound.OSC.FD as O
udp <- udpServer "127.0.0.1" 6012
r <- openUDP "127.0.0.1" 6011
sendMessage r $ Message "/code" [string "hello", string "sound \"bd sn*\""]
The interpreter thread doesn't crash, but the whole of tidal-listener does! So the exception isn't raised in the interpreter (which is what we want) but later, when the parsec parser is invoked on the mininotation. So we want some exception handling elsewhere, probably similar to how Sound.Tidal.Stream works, where it catches an exception it returns to the previous pattern.
We should also try to make things as strict as possible so we can catch these errors before updating the pattern state. Just forcing the first cycle to be calculated would be fine.
Or we could do probably something fancy with template haskell, so that the parsec parsing is done during typechecking.
Thanks to @polymorphicengine we have a tidal-listener building into a relocatable binary, great ! We should make use of this for the next tidal release.
We could distribute a ghci drop-in replacement. @jwaldmann already made this: https://github.com/jwaldmann/safe-tidal-cli . It looks good and is safe for exposing to untrusted users (e.g via flok), although doesn't support definitions with
let
.Or we could skip that and prioritise editor support for the OSC API.
I quite like the idea of turning tidal-listener into a multi-function tidal engine, that can act like a ghci session, act as an OSC API over UDP, or run a web server serving up a codemirror based interface, depending on what parameters are given..