-
Notifications
You must be signed in to change notification settings - Fork 1
/
TODO
298 lines (259 loc) · 12.7 KB
/
TODO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
* Problem:
If you use too large note durations (like 1000000ms),
you will not be able to restart the interpreter because it is waiting.
* Bug:
If file name differs from module name then symbols will not be highlighted.
* Example:
Music using Markov chains or Markov models.
Markov chains: manage lists about what notes can follow after other ones
Markov models: use chords as state and appropriate notes as output
* sharing
Support sharing by providing a restricted form of 'let'
or by providing a 'lambda' with sharing.
Sharing simplifies handling of Wait times in 'merge'
and the current state in 'iterate'.
Currently we have to use a bunch of complicated strictifying functions
that evaluate the state immediately instead of splitting it first
and compute the duplicated terms separately later.
In the source code 'let' could be written everywhere,
but in the current term I think it is easier to have only one global 'let',
since we have to update its definitions frequently.
On the other hand a global 'let' requires disambiguation of local identifiers,
which might then conflict with top-level identifiers.
However, even with local 'let's we need identifier disambiguation.
Since local identifiers shall not be affected by program updates
we could make local identifiers distinct from global ones
by prefixing them with '%' or so.
We also need a kind of garbage collection.
If a 'let'-bound identifier is used
* zero times, then its definition should be removed,
* once, then its call shall be unfolded,
* more than once, then everything should remain as it is.
A typical reduction could start here:
let y = f x
in g y (h y)
Say, we must match the first argument of 'g',
Thus we have to reduce 'y' once,
this may result in:
let y = Cons z
z = ff x
in g (Cons z) (h y)
Now 'y' is used only once and
this should make the garbage collector rewrite it to
let z = ff x
in g (Cons z) (h (Cons z))
An interesting question is how often shall we run the garbage collector?
After every reduction or after every list element?
Additionally at user demand?
* avoid space leaks
Add a hard-wired function, say 'simple'.
'simple' is reduced at every garbage collection,
if its application does not require reductions of its arguments.
This would avoid a space leak in:
let x = splitAt 2 "abcde"
in fst x ++ simple snd x
But it would only work, if the 'snd' in 'splitAt' is 'simple', too.
I think in GHC all record accessors are 'simple' in this sense.
I think we should just mark such functions as simple.
* reload and parse module if file is modified on disk
This way we could also allow editing modules in command-line mode.
But also in GUI mode it would simplify the work with external editors.
Package 'hinotify' is what we need, but it depends on UNIX.
* under Ubuntu the splitterwindow position is the left-most on startup
This behavior is not nice, but I do not know how to improve it.
At least it would be good if moving the sash in one module
moves it in others modules as well.
I do not know how to do this, as well.
Maybe it would work better if we could set the sash gravity to 0.5.
Currently this function is not provided by wxcore.
* move to new explicit-exception version and use its Exc.switchT
* rename module - rename imports?
When renaming a module it would simplify editing a lot,
if also imports would be changed.
Changing the module in the interpreter is relatively easy,
since it is already parsed.
We know the source position of identifiers,
thus it is possible to replace the identifiers in the interpreted module's source
and thus we could update the display of the interpreted module.
However modifications in the interpreted module
will be lost on the next module refresh.
Thus we must alter the edited module too.
But the edited module may not be syntactically correct.
We may only parse the preamble.
Or we may only parse the longest prefix that is a correct preamble.
And I think we must do the modification immediately in the GUI
in order to make it atomically.
* read-only TVar 'program' for interpreter
We could define a wrapper around TVar that allows only reading.
This should be used for the interpreter.
* layout of controllers
How to arrange a set of sliders and checkboxes?
Should this be done automatically?
Should the user be able to arrange the elements interactively?
Should the programmer be able to specify a layout as functional expression?
* shall sliders and checkboxes have distinct namespaces?
Currently it is checked that sliders and checkboxes cannot have the same name,
but we maintain values for sliders and checkboxes separately
in order to make rules in Controls and stored values in Program.controlValues consistent.
* Module system:
support qualification and all styles of imports
when refreshing a module, I think we need a global check of all imports
check for existence of imported and used qualifiers
export lists
hierarchical module names
-> use Helium
* The current term is actually not current,
it shows the last state.
This is a problem, when we apply a function to the current term,
since then suddenly a different term pops up.
It may become even more a problem,
when we allow more fine-grained reduction steps.
We could thus divide the current term into the 'head' and the 'tail'.
Maybe we can even display 'head' and 'tail' separately.
In a left sub-window we could list all emitted events
and a right sub-window we could show the real current term.
* Library part
Move modules into module hierarchy.
* pair syntax (a,b)
We could make "," a regular infix operator with low precendence.
This would give us operator section syntax.
However it conflicts with commas in list syntax.
We should just let the Helium parser solve this problem.
* Are newlines in module content from HTTP handled correctly?
WWW uses CR+LF
I have observed, that Windows/InternetExplorer submits CR+LF in the modified text lines.
The question is, what kind of line end is expected by WxWidgets?
* Are encodings in HTTP handled correctly?
Currently it seems that browsers prefer to send UTF-8
and HTTPdshed can read this.
But I am afraid that other browsers or other browser configurations
may easily crash the live-sequencer with umlauts and other special characters.
* higher order functions:
support operator sections like (+) and (:)
Can expressions like (a+) and (+b) be handled by postfix and prefix operators?
This won't work, because operator sections are only allowed in parentheses.
E.g. (a + + b) is not valid syntax.
However it is allowed to write (a+b+).
But due to the left-associativity it is not allowed to write (+a+b).
Is it allowed to use the same operator as infix and postfix symbol?
Maybe at the beginning I should only support (+), but not (a+) and (+a).
Since operator section is only allowed in parentheses
we can handle it in the parser of syntactic atoms.
support lambda
* Gtk-CRITICAL warnings: eliminate them
sometimes the program crashes on exit
* GUI graphical error:
between menu and tab handles there is a short line,
that looks like the top border of another handle
does it have a meaning?
* precise ALSA timing
For precise timing it is certainly better
to send ALSA events with future time stamps.
Currently we wait using ALSA echo events
and then send the actual event immediately.
The proposed change increases latency of changes in the source files.
Current term and highlighting should be updated
when the delayed MIDI event is played.
We can achieve this by sending an Echo message to ourselves.
We already send Echo messages to ourselves.
We should use two kinds of Echo messages:
One of them triggers evaluation, the other one triggers visualization
and has the same time stamp as the according ALSA time stamp.
We need to start and stop queues with the same latency.
.
We can even hide the latency by starting the computation non-stop
until the timestamps of the computed events are
sufficiently ahead of the actual current time.
When we stop the queue this will also happen instantly.
* JACK support
We should support JACK
in order to control multiple synthesizers
simultaneously and with precise timing.
JACK is also portable in contrast to ALSA.
To this end it would be great
if we could cleanly separate MIDI handling
from the remaining application.
Maybe reactive programming can help here.
Today this seems to be even more important than PortMidi support.
* PortMidi support
We could fall back to threadDelay timing
and WX-timer event for polling incoming MIDI keys.
We could even achieve precise timing with PortMidi
using PortMidi's latency, rough waiting using threadDelay
and synchronization using PortTime's 'time' function.
* Dirk Richter proposes to store old module contents when updating a module.
This way you can later reproduce what you did in a live performance.
* use haskell-src(-exts) for parsing,
to be sure we have a subset of haskell
haskell-src: no support for precedence and associativity
haskell-src-ext: no support for source locations
better: Helium parser supports all we need
* Can we use reactive-banana-wx in order to write safer GUI?
Maybe we can simplify:
mutual exclusive menu items
consistency Map Module.Name Page with GUI pages
synchronization of ALSA and WX and HTTP,
e.g. various inputs to the text field; execution modes
Peter Pepper: "Acausal programming"
* demand trace/"backtrace"/GUI:
distinguish between musical and operational highlighting
as described below, highlighting according to NoteOn and NoteOff won't work
and it would also not solve the problem of dependencies
We could maintain a map of currently played notes
in order to switch off highlighting for these notes,
when NoteOff is send.
This would correctly de-highlight notes,
but the backtrace would still be cumulative.
Interesting observation:
in a 'repeat' the last notes are turned back to normal appearance
if the loop starts again
* compositional highlighting
The composition of note streams shall also compose their highlighting animations.
Currently active terms are highlighted during a Wait event,
but those Wait events are shortened by 'merge'.
Actually, all active terms should only be highlighted
for an infinitesimally short time.
For music highlighting we could highlight terms from NoteOn to corresponding NoteOff.
This would not work -
if NoteOn is wrapped in f and NoteOff is wrapped in g,
then on NoteOn the highlighting of f is switched on
and on NoteOff the highlighting of g is switched off?
Instead I think we must highlight the complete "backtrace" for the active term
(or at least the Wait, since this is what we really show)
* merge editor and highlighter window
track all inputs of the editor window and
adapt the information in the syntax tree accordingly
I am not sure that this is an advantage.
Maybe there should be two windows:
One with the editor and one with the interpreter content and the current term.
This way you can project the interpreter content to the wall
and edit in the editor privately.
* Maybe we should use WxWidgets feature for external GUI description.
This way, the user can choose the arrangement
of editor, highlighter and current term area.
We could also have translated versions without recompilation.
* add a type checker to the implementation
Try to incorporate Helium/parser/type-checker or Typing Haskell in Haskell.
Can one of the special Haskell editors Yi or Leksah be of help?
* check all head, read, error, unmatched patterns, irrefutable patterns, print, putStr stderr,
toProgram, toPitch, toVelocity,
readFile, writeFile and other IO functions,
whether they should handle exceptions
especially in Program there are currently too many 'errors'
problem: there will be no warnings about patterns in monadic results
e.g. (Number rng n) <- top
* handle for resizing parts of the window
even better: a way for rearranging parts of the GUI
this would allow to arrange text fields horizontally
such as required for wide aspect in YouTube movies
* bug: when changing a module you might remove a term,
that is still present in the reduced term
In this case, the highlighter will highlight its original position.
Reproduce it by: delete the 'repeat' in Simplesong and refresh -
the former position of merge is highlighted
* cabal test:
check whether modules in 'data' can be parsed by our parser
check whether modules in 'data' directory can be compiled by GHC
* maybe split Term into Parser and Term module
* allow IO or restricted IO monad
such that the live program can send the messages itself