forked from olofson/eel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TODO
1121 lines (908 loc) · 39.3 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
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Audiality 2:
* Port:
* renderwave3.c (A2 ticket #188!)
audiality2.h:
==> * How do we deal with substates being destroyed by A2 along
with their parent state!?
* a2_*Callback():
Need dedicated asynchronous VM state!
* a2_ConvertSize(), a2_Convert():
Not yet implemented in A2!
drivers.h:
* a2_OpenConfig(), a2_NewDriver(), a2_AddDriver() etc:
Covered by Open(). A2_config is not explicitly wrapped.
* The driver implementation interface is mostly irrelevant at
this point, as it would require dedicated EEL VM states to be
of much use, just like units.
dsp.h:
* Could wrap this, but it's just inline DSP math utilities, so
it makes little sense.
properties.h:
* All currently available props exported.
* a2_SetProperties():
Leave for now. Only used internally, by a2_Render().
types.h:
* Interleaved format flags not exported - but they're not yet
implemented anyway!
units.h:
* Needs dedicated asynchronous VM state!
vm.h:
* Needs dedicated asynchronous VM state! (Only relevant to
units and possibly other realtime context callbacks.)
waves.h:
* a2_GetWave():
Very low level interface, only relevant for oscillator
units and introspection code.
* Should we bother porting renderwave.c? It uses the "buffer" audio
driver, which basically just leaves it to the application to dig the
buffers out of the driver struct. The stream API should probably have
a backend for this, so we can just read a stream, and have that run
the off-line A2 state.
* There is a2_Render(), which *writes* to a stream. (It's used
by a2_RenderWave().) Not sure if that's useful somehow...
* Should we just treat Audiality handles like plain integers, as in
the C API, or should we wrap them and wire them to EEL memory
management?
* Instead of the (inefficient) OO API, we could go back to a straight
call API with explicit state arguments. That way, we could just
ignore calls if the state argument is nil, instead of implementing
dummy states in A2.
* Register dependency checking for the optimizer:
eel_r_dependency(EEL_coder *cdr, int r, int pc)
{
if(r is allocated)
return HANDS_OFF;
for i in instructions[pc, end_of_fragment]
if instructions[i] depends on r
return HANDS_OFF;
return NO_DEPS;
}
* Overwriting an existing environment variable in envtest.eel;
"setenv(TESTVAR, "new_test_value", false);" succeeds under Wine 1.4.1.
This should fail, regardless of platform!
* Run some VM profiling to see which instructions are actually used!
* Shouldn't INDGETI etc use EEL_IS_OBJREF instead of switch()...?
* try ( <expression> : <fallback> )
* var bestValue = points?.FirstOrDefault()?.X ?? -1;
* Don't actually use THROW for RETX*...
* Memory management needs a cleanup...
* Why is eel_context_push() using eel_malloc(), for example? The
compiler is NOT to be used in realtime context!
* Are we using eel_malloc() etc where intended?
* There are some functions in the builtin module that probably belong in
system.
* Should the builtin module really be imported by default?
* Some string formatting tools would be nice...!
* Would be even nicer if the full range of bases of the compiler were
supported as well.
* Parser tool that takes an input stream (memory or file), a state object, an
output stream, and one or more token and/or pattern matching tables, and
either copies the value fields from matched elements, or if they're callable,
calls them with the match buffer, the state object and the output stream, so
they can do whatever they want.
* EEL probably has the same bug that I reinvented in Audiality 2: If the
last token is invalid (after Unlex() usually), the start position is
bogus, and should not be used!
* Accessing parent function arguments (upvalues) from within
'try' handlers seems broken in strange ways, at least when the
arguments are optional. Arguments come out of order or
something...
* Probably shouldn't bother with this. The whole idea of
implementing exceptions as actual function calls is
fucked up anyway.
Also Kobo II - uninitialized hashes in tables...?
==28430== Conditional jump or move depends on uninitialised value(s)
==28430== at 0x4E5DD53: t_getindex (e_table.c:185)
==28430== by 0x4E466A9: eel_run (e_operate.h:146)
==28430== by 0x4E501BA: eel_call (e_vm.c:2802)
==28430== by 0x4E502DF: eel_calln (e_vm.c:2905)
==28430== by 0x40536C: main (eelbox.c:306)
==28430==
==28430== Conditional jump or move depends on uninitialised value(s)
==28430== at 0x4E5DF95: t_getindex (e_table.c:185)
==28430== by 0x4E466A9: eel_run (e_operate.h:146)
==28430== by 0x4E501BA: eel_call (e_vm.c:2802)
==28430== by 0x4E502DF: eel_calln (e_vm.c:2905)
==28430== by 0x40536C: main (eelbox.c:306)
==28430==
* PUSHA instruction for pushing items of an indexable object as
arguments + language syntax for using that in argument and
initializer lists?
* Syntax:
local args = [...stuff...];
SomeFunc(#args);
* PUSHAS and PUSHASR for specifying slices via immediate
operands and registers?
* Limbo lists revisited:
* When and why are they still needed?
* What's the deal with temporary objects created when evaluating
expressions? The current problem is that these objects will
leak unless someone keeps track of them, since normal VM
register access bypasses refcounting. Maybe we should just
treat work registers like any reference owners and be done with
it...? There is overhead and complexity SOMEWHERE no matter
what, and limbo lists are looking like a bad deal now - and
ever more so on 64 bit platforms, where they add 16 bytes to
every single object! Also, an object only being able to be in
one limbo list at a time further reduces the usefulness.
* Out-of-band destructor field for tables? Other classes?
if(table->destructor)
{
EEL_object *to = EEL_table2o(table);
++to->refcount; /* Prevent infinite recursion! */
eel_callf(to->vm, table->destructor, "o", to);
}
* What about the new argument expansion feature in explist(); are
there cases where we can't allow run-time variable length of
the the resulting lists? Most cases will be trapped when the
compiler tries to do things that aren't allowed by the manipulators,
but we need to make sure we don't have odd cases that generate bad
code.
* Texture filtering flags not working...!? (Kobo II gfxmanager.eel.)
* Add some flag or something to UploadTexture() to keep it from
changing the min/mag filtering settings on existing textures!!!
* Add support for uploading from plain EEL vectors and similar to
OpenGL...?
* No-normal-case-cost exception handling:
* No TRY instructions or similar!
* Compiler builds a list of "exception trap zones" for each
function, each zone specifying VM code start/end and
what to do in case of an exception.
* Normally, the VM does nothing, and doesn't even look at
this info.
* In case of an exception, the VM checks the PC and looks
up the corresponding zone. The simplest implementation
would probably be to just compile the "except" block as
a function as we do now, and wire the exception trap
zone to that.
* snfprintf() wrapper!!!
* Might be an idea for eel_export_lconstants() to fail if an
existing constant is redefined...!
* Add miniz...?
* Physics:
* Simple "sticky" constraint that generates friction
between two bodies as long as they overlap.
* "Attach" constraint...? (A bit like "sticky", but also
includes a spring factor and desired position and
orientation.)
* Use the constraints system for applying "long time"
forces...? (Constraints operate via forces now anyway;
that might change, though.)
* Downside (?): Not owned by bodies...
* Constraints should act on rf[] not f[]! No issue as long
as we're using IMPULSEFORCES - and we should be using
"objectified forces" (implemented as constraints?) for
that event driven AI stuff anyway...!
* Add velocity aware tests for fast moving objects!
if(max(abs(dvx), abs(dvy)) > APPROX_MAX_DELTA)
subdivide_test(..., APPROX_MAX_DELTA);
* Build 2D and 3D float vector types into the VM, as
native value types...?
* Shapes: "...providing different areas of the same object
with different friction, elasticity or callback values."
* Per-body or per-shape collision response parameters.
* Body 'e' field not implemented!
/*
* Read 'count' elements from vector 'v', starting at 'start',
* into 'buf'. 'vstride' and 'bstride' is the step size used
* when reading the vector and writing the buffer, respectively.
* Returns 0 if the operation is successful, otherwise an EEL
* exception code describing the problem.
*/
EELAPI(EEL_xno)eel_iread_i(EEL_object *v, int start, int vstride,
int *buf, int count, int bstride);
EELAPI(EEL_xno)eel_iread_f(EEL_object *v, int start, int vstride,
float *buf, int count, int bstride);
EELAPI(EEL_xno)eel_iread_d(EEL_object *v, int start, int vstride,
double *buf, int count, int bstride);
/*
* Write 'count' elements from 'buf' into vector 'v', starting
* at 'start'. 'vstride' and 'bstride' is the step size used
* when writing the vector and reading the buffer, respectively.
* Returns 0 if the operation is successful, otherwise an EEL
* exception code describing the problem.
*/
EELAPI(EEL_xno)eel_iwrite_i(EEL_object *v, int start, int vstride,
const int *buf, int count, int bstride);
EELAPI(EEL_xno)eel_iwrite_f(EEL_object *v, int start, int vstride,
const float *buf, int count, int bstride);
EELAPI(EEL_xno)eel_iwrite_d(EEL_object *v, int start, int vstride,
const double *buf, int count, int bstride);
---------------------------
* Exception handling segfaults:
* There *should* be garbage in the argument stack if
there's an exception thrown while constructing arguments,
right...? Who's supposed to clean that up!?
* What about C functions...?
* Looks like an exception inside a C function results in
the VM trying to unroll twice...
1. Unwinding must include the C stack!!!
2. ???
* Still segfaults when cleaning up after dumping.
* Exceptions trigger a VM dump whenever we transition from
a native function back into the VM, but that shouldn't
be more than a bandwidth issue...?
---------------------------
* EEL 'clean' function for cleaning out nil refs (as in, dead
weakrefs) from arrays? (Might need a "back-index adjust" feature
to be of much use.)
* Maybe we need a proper objref list class for this?
* EEL needs to make proper use of the argument stack when
compiling large constructors! As it is, it runs out of
registers, just as it did before the argument stack.
It might be a good idea to collect up to four items,
to make use of PUSH2/3/4. More than that is pointless,
though, if not suboptimal in terms of performance.
* One way to deal with the EEL_T*/EEL_C* warnings without
losing the "trapping unhandled EEL_T*s" feature:
* Put them all in a single enum.
* Create a DEBUG macro that evaluates to the full
list of non-EEL_T* symbols in DEBUG mode, and
nothing (ie implicit default) in release mode.
* Operator cleanup:
* Remove all nonsense "special" operators!
* Switch to a specific concatenation operator!
* Implement array concatenation!!!
* Remove the specific vector operators?
* Rename |< and >| as 'min' and 'max'...? Or
remove them, and throw in some nice builtin
functions? min(), max(), clamp(), ...
* Convert ZeeSpace to the same naming conventions as my
other projects; ZS_typename - not ZS_TypeName!
* EELBox should reload OpenGL automatically after
restarting the video backend!
* Generic 2D arrays in EEL core or dsp?
* Interpolated Get()/Set() methods.
* 2D vector operations.
* Graphics rendering operations.
* Tools for converting to/from surfaces/textures.
* Later on:
* Interleaved buffers, for interfacing
directly with SDL, ZeeSpace and OpenGL.
* EELBox should perhaps have
* AAPlot()
* Line()
* AALine()
* ExtractColor() (return [r, g, b, a])
* Future of EBGUI and the K2 GUI: Strict MVC design!
* GUIs should be defined using markup and/or
dedicated EEL modules - no "inline" code!
* Application/GUI interaction is done entirely
using messages. (Like parts of EELSynth.)
* Optionally, widgets can be "wrapped" locally
as a way of keeping state data accessible, and
automatically synchronized.
* Support callback notification?
* "End of message queue" notification callback
for widget implementations! This would make it
trivial to implement mouse move filtering and
similar on the widget level.
* EELBox OpenGL should be wired so that any EEL call
before loading OpenGL just results in an exception - not
a segfault!
Temporary hack: All calls wired to a dummy that prints
a warning message.
* Putting function references in static tables creates
memory leaks!
* Lots of new, interesting warnings to sort out...
* Various examples broken!
* ZeeSpace demos using removed APIs!
* Owner trace debug call!!! Figuring out why objects are
unintentionally kept around is hopeless as it is.
* Avoid the extra weakref relocation sweep when inserting
items in tables and arrays!
* zsdraw editors seem to be deleted when closed, but leave
empty tables. That is, weakrefs not working properly.
* "WARNING: Discarding event for dead body"...? Should
that actually ever happen? Some limbo list or local
variable holding on to dead bodies in the loop...?
* INDGET* --> LDIND*, maybe...
* INDGETC, PUSH ==> PHINDC
* ADDI, SUBI, ...
* Dedicated operator instructions for the most common
logic operations!
* There are a lot of 'GETARGI ARGS[x], Ry' all over the
place in OO style code. Can we optimize that somehow?
* One option is to put some or all of the
required arguments in registers.
* Since they're memory managed via the
argument stack, there's no need to
handle those regs as stack variables.
* VM needs to special-case these in SETARG!
* Compiler must not issue SETARGI for
these arguments.
* Another option is to implement more instructions
for the common cases. Probably faster, but we're
getting a lot of instructions here...
* JUMPEQ, NE, ... (matching the *BOP* ops)
* EQ, NE, GT, GE, LT, LE
* AND, OR, XOR
* IN
* *I versions?
* BOPC, PHBOPC...?
* Peephole optimizations:
* Remove CLEAN before RETURN. (???)
* Tail calls! (TCCALL* + easy peephole optimization.)
* What about registers that are left unused after
optimization? They'll usually be on the top of the
register allocation stack, so no holes - but they may
still impact the function frame size. Perhaps we should
base that on the highest register actually USED instead.
* PUSHRC, PUSHCR, PUSHRI, PUSHIR
* TRY with no except block; ie ignore exceptions.
* Upvalues!? We should verify that functions called with
CALL aren't trying to use upvalues!
* Maybe arithmetics on nil should throw an exception?
* true == (integer)1 and (real)1? (Many languages treat
'true' as a non-value, but being able to multiply with
a boolean is handy - and suggests that true == 1.)
* We could basically just do away with the cleantables,
but then one has to deal with "object buildup" in loops
and the like in some other way.
One way is to give the callframe a LIFO stack of limbo
list headers, but that means we need to insert
instructions to deal with that.
However, when does this buildup problem actually
occurr? It happens in loops, where there is no naturral,
safe place to clean up, such as when leaving the
function. So unless there is a loop, there is no problem!
Thus, we could have the compiler give each looping
context that *can* generate objects, a limbo stack level,
and add that to the relevant instructions, so they can
add any new objects to the correct limbo list.
Jumps that restart or leave limbo contexts will need
to be coded with special instructions that clean the
apropriate limbo lists when leaving contexts. These
instructions should probably name the target context
limbo level, and VM logic should clear any limbo stack
levels used above that level.
* What about objects that are already in some limbo
list? Is this guaranteed to always keep the
object alive *at least* through the lifetime of
our context? (Context that write objrefs to
registers belonging to outer contexts will have
to move the objects into the appropriate limbo
list anyway.)
* Efficient solution for passing arguments directly on to
a callie, and/or putting them in an array...?
* The callframe argv and argc could be derived from the
return info r_sp and r_sbase. Do we actually need argv
and argc?
* Add PUSHI2 (2x sint16), PUSHI3 (3x sint16) and PUSHI4
(4x sint16).
* PUSHCR (Push Constant Range) instruction! There seem
to be quite a lot of PUSHCing of contiguous blocks of
constants...
* New C function prototype:
EEL_xno fn(EEL_vm *vm,
EEL_value *argv, unsigned argc,
EEL_value *resv);
* Allow resv == NULL for "result not desired"?
* Use this for constructors as well? (Only diff is
that EEL_ctor_cb has a 'type' argument.)
* Qsort!!!
* EELBox etc should pre-lookup EEL strings rather than
dealing with C strings when constructing SDL events and
the like!
* Number of available CPUs from "sysinfo" module!
* OpenMP/GOMP!?
* Script profiler! Keep a counter for each source code
line (or VM instruction) of every function.
* Unify limbo lists and clean tables somehow? Or can we
deal with stray objects in some other way?
Or do we just move to pure refcounting, initializing
and clearing all registers, brute force? This may sound
horrible, but:
* The cleantable adds per-INIT overhead anyway.
* The cleantable cleanup touches ALL used regs!
* Special instructions are needed for dealing with
variables vs "normal" registers.
* Limbo lists are required for dealing with objects
that may end up never being assigned to a proper
variable.
* With static typing and/or type infering, a lot
of registers can be eliminated from the init
and cleanup, as they'll never hold objects!
* Command line executives: It's probably a good idea to
list function headers and VM disassembly when specifying
-a without -l, rather than just listing nothing...
* If available, print source code along with the line
numbers in VM dumps!!!
* Optionally do this for -la as well!
* An EEL callable C functions that call EEL functions has
to be aware that a VM heap reallocation may occur,
invalidating its argv pointer! Should we just leave it
at that, or keep the old vm->argv, which can be updated?
Or somehow fragment the heap, and disallow reallocations
altogether. (An argument stack overflow would instead
start a new heap fragment and move the current stack
there.)
* Separate typeid types for values and objects? (That is,
use EEL_classes instead of EEL_types for objects.)
* Constructors to become normal functions?
* Why are the operands swapped for object_rop() in
e_operate.c? The only "reverse" thing about it is
actually that only the (actual) righthand operand is
guaranteed to be an object, whereas for object_op(), it's
the lefthand operand that is an object. (object_op() also
covers both operands being objects.)
* New module management?
* All module constructors must RETURN a module.
* No more dead/zombie modules!
* Shared modules are kept in 'modules'. Weakrefs!
* Cleaning is just scanning 'modules' for any
modules that are back at their initial refcount
sums.
* "Locked" (built-in) modules are just given an
extra incref. (*After* calculating the refcount
sum, obviously!) When cleaning up the state, one
just scans 'modules', decrefing, and then does
a final module garbage collection that *should*
remove any remaining modules.
Then again, the old solution *should* work. There is
something fishy here...
* Merge EEL_state into EEL_vm_private?
* Swap operator?
* Add a "nothing" or "void" type/value, that cannot be
generated by normal code, to mark "no return value"
from vacall() and things like that?
* eel_get_current_moduledata() doesn't work for
constructors! (A constructor is not a function as far as
the VM is concerned.) How to deal with this...?
* EELBox:
* OpenGL:
* Custom mipmap generator?
* ZeeSpace:
* zs_Blit2SDL() needs a source rect and target
coordinates!
* zs_Render3D2SDL() needs a target rect!
* zs_Blit():
* Plain copy (?) reduces intensity!
* Add some more drawing tools for regions:
* Perlin terrain
* Dome, beehive, cone etc.
* Spline surface
* Surface transform
* Implement region boolean operations!
* Add more region construction tools!
* Various filters!!!
* IIR and FIR smoothing
* Selective smoothing
* Distance blur (z modulation)
* EEL readback of all Pipe fields!
* EEL clone for Region and Pipe!
* ZeeSpace Draw:
* Workspace should only be redrawn ONCE as a
result of any number of entities or areas
needing a refresh!
* Proper entity list!!!
* Selection highlight.
* Entity IDs?
* Realign after deleting entities!
* Maybe the background entity shouldn't be
deletable? Or we just make it a normal entity,
only without size and location.
* CLI?
* Numeric size/position editors!
* Grid + snap!
* Polar "grid".
* Grid wrapped over surface.
* Multiselect!
* Handles can end up outside the workspace,
visible, but not accessible!
* Scroll!
* Zoom!
* Undo/redo!
* EBGUI:
* Resizable windows! (SizeHandle widget?)
* Selection logic? Multiselect?
* Hook for processing widgets as they're added?
* Standard popup menus!!!
* Click() should have a button argument?
* Can we somehow support children that are not
constricted to the client area of their parent
widgets...?
* Mouse motion filter!!!
* Deliver events as arrays?
* Add a "further events in queue" flag?
* Invalidate() doesn't always work. See entity
widgets in ZSDraw; tab navigation doesn't redraw
the previous widget as unfocused.
* ListBox scrolling behaves a bit odd at the
bottom end of the list.
* Calling a procedure via "reference" (ie via table)
generates a result that is the function itself!!! This
should obviously result in some exception instead.
* Add "read from stdin" feature to 'eel' command!
* The FFT module is apparently not thread safe!
* EEL_OWNER_TRACE segfaults!
* The whole thing is broken anyway. Removing...
* A better solution would be a tool that finds
all objects (DBGM()...) and presents objects
as a tree or similar.
* Normally, all objects should be possible to
find by scanning the modules - but circular
references may keep other objects around!
Maybe container objects should register
themselves somewhere whenever they receive
a reference to another container?
Also, a self-reference obviously needs to
refcount! One just needs to handle it
properly (as in ignoring it) when destructing.
* Operator for concatenating a weakref to an array,
corresponding to "a.+ o". "a.(+) o"? Typecast to
weakref?
* Remove *_v_own() and similar...?
* Start on some visual introspection debugging tool...
-----------------------------------------------------------
Long term:
* Modules:
* Fix the module loading catch-22 etc...
* Injected modules are instantiated by
EEL callable functions, or actual EEL
functions, that are added to the
environment.injected_modules table.
* Is the unload callback still needed?
* What happened to eel_import()?
* Build a new warning/error message handling system
based on EEL types!
* Messages are EEL tables with fields like
"type", "sourcefile", "line", "column", etc.
* The message log is an EEL array of tables of
the aforementioned format.
* When dumping or otherwise aborting, error
output is formatted by EEL code in the built-
in library, avoiding C code to save space.
* The message log can be accessed by EEL code.
* Why compile 'try' and 'except' blocks as functions?
Well, it seemed like the easiest way at the time...
* At least, 'except' blocks have no real reason
being functions. They should be handled just
like the 'else' blocks of 'if' statements.
* Now, what's so special about 'try' blocks?
They may look much like "breakable" loops -
except in a 'try' block, any instruction that
throws an exception will be the 'break'. The
hairy part is the cleanup. When coding a
'break', the compiler knows which variables
have been initialized, so it can code a CLEAN
instruction as needed before the JUMP. At run
time, this information is not available, as
the VM isn't really aware of local scopes.
* Can we just store the current variable init
state at the start of the try block? (The
cleaning table keeps track of the number of
total inits.) That way the VM can effectively
issue a CLEAN instruction as needed, before
jumping out of the 'try' block.
* Multiple quoting for strings!
* Do something about hashes for strings longer than 32
bytes? (Do every N'th byte, include the length in the
hash, ...)
* 'try'...'finally'.
* Special operator for concatenation? Typically, one
can rely on context (lefthand and righthand types)
to determine if '+' should concatenate or add
arithmetically. However, adding vector operations
to the mix eliminates that possibility, and one must
explicitly express what's desired. (Currently, EEL
does this by using a special set of operators for
vector operations: #**, #%, #/, #*, #- and #+.)
Concatenation operator syntax options:
* # Similar to +, which makes sense.
* ## (C preprocessors)
* ~ Conflicts with "bitwise not"!
* . Conflicts with "OO style" indexing!
* With the cat/add conflict eliminated, remove the
weird #+, #* etc operators.
* Concatenating a function to a table should create
an item with the function name as key and the
function itself as value!
* There should be an easy way for "add-on" types to
provide table functionality, so one could add
things to them at run time.
* Maybe support "private" add-on fields,
that can normally be seen only from within
a limited scope, such as the current module?
(Unique prefixes to the field names.) This
would allow independent modules to tag
various objects without risk of conflicts.
* 'try' block shorthand? Trying to retrieve a value
somehow, and if that fails, grabbing a default value,
is a rather common operation.
* What was the idea with a return code from class
unregister callbacks? Useful for what?
* "Slice reference" objects.
* Can this be done in a generic way, for
all (integer) indexable types?
* What to call the type(s) and calls?
* Optimized sort()! Should take one or more
indexable objects, where the first one determines
the order, and the other ones, if any, are
rearranged in parallell.
* Brute force search function:
* function find(obj)[start, end, stride];
* Smart find for sorted containers:
* function sfind(obj)[start, end, stride];
* Priority queue type.
* file.sysroots() to get / or C:, D:,
... or whatever the system at hand deals in.
* Threading with inter-state "IPC". (spawn()?)
* 'in' operator/keyword, for
* for local x in y ...
* Testing if a value (key, in the case of
tables) exists in an indexable object.
* DSP Generator Objects:
* Native EEL objects
* Constructors with arbitrary parameters
* GETINDEX metamethod generates output
* COPY generates a vector of the algorithm's
native data type, filled with output.
* SETINDEX may be used for seeding and
other parameters
* CAST metamethod generates a single value
* Self-documenting modules!
* TLSF memory manager
* Add void * field for mmgr pointer
* Extending the pool...?
* Make this an optional module?
* Finish the serializing/deserializing subsystem.
* io.read() and io.write() should support more
types! (Should really be using the
(de)serialization subsystem.)
* New type/class system:
* Type IDs are removed, or possibly
degraded to a central unique ID registry
service. (Built-in types are hardcoded
and preregistered, as in EEL 0.1.x.)
* Every Object has a Class pointer ("VMT")
* Every Class has an origin module pointer
* Modules export Classes like any exports
* Inheritance...? Probably not!
* Metamethods should be proper functions,
as in EEL callable C functions with
normal argument passing.
* The most common metamethods should be
kept in a table in the class object.
* Additional metamethods are registered
by name, and arranged in a suitable
quick look-up structure.
* Multiple returns:
* Consider the cons and pros, considering
that it's easy enough to "fake" it by
returning an array, table or whatever;
* Actual usefullness
* Performance gain?
* Added complexity
* Declaration:
* function (ret1, ret2, ...)
funcname(arg1, arg2, ...)
* No return list, or an empty
return list, implies a single
return value.
* Results are considered optional!
* Space for the returns is allocated on
the argument stack before any arguments.
* The function is told how many arguments
are requested.
* Check with 'requested' in EEL functions.
* EEL 'return' must check that enough
values are returned at run time!
* EEL 'return' will ditch unwanted returns.
* Fragmented arrays!
* Fast and deterministic insert(), delete()
and similar.
* Indexing can become expensive,
alternatively, a "quick index" must
be maintained.
* Direct access to data from C code
becomes complicated.
General
-----------------------------------------------------------
* Default values for optional arguments! After switching
to the argument stack for calls as well (used only for
constructors as of 0.1.15), this is trivial. The CALL op
code would just grow the stack to the full size of
required + optional arguments, and fill in any missing
arguments as needed. (Obviously, tuple arguments will
remain the way they are, except that when specified,
they're pushed onto the stack.)
This would make required, optional arguments, and
specified tuple arguments writable, and it'll probably
make closures and coroutines easier to implement. This
would eliminate the current ugly manual wrapping using
local variables, and it would also allow C++ style
default argument value notation as an alternative to
'if specified ...' and similar constructs. (The latter
are still handy in many cases, though, and cannot be
replaced entirely.)
* "Reverse" extended error/exception handling: When things
go wrong, *first* check what the VM wants to do about it,
then proceed according to that information; either just
give up with a simple EEL_X* code, or build an object
with detailed information.
This can be wrapped in a macro that appears to format
error messages printf() style and then returns a value,
but actually checks if anyone wants the information
before even looking at the formatting stuff.
This logic can probably be carried over to EEL code
as well, where it's even more desirable due to the cost
of formatting error messages in EEL code. Maybe a second
"argument" to throw, evaluated only if the information is
desired? It could be compiled as an anonymous function,
similar to how try blocks are handled.
* A dynamic interface negotiation system is needed for
inter-module dependencies. (Modules are not necessarily
built and installed like proper shared libs, so it's not
safe, and may not even be possible on some platforms, to
link to modules!) The same solution should probably be
applied to the EEL core interface.
* Remove the "if(constant == variable)" nonsense in the C
code.
* Test the DBG() #defines and fix or remove broken or
irrelevant debug code.
* e_register.[ch] needs splitting and cleaning!
* There should probably be "table of struct" interfaces
for all registration calls, not just constant exports.
* Use a special indexable type for command line arguments?
This would eliminate the argument count limitations.
OTOH, with the current solution, the stack should grow
automatically as needed, right...?
EEL core
-----------------------------------------------------------
* The sed script that turns the EEL Built-In Library into a
C string should strip comments and whitespace.
* Debug info + source listing in VM dump output.
* 'break' from within 'try' and 'except' blocks! The try
or except block function should probably throw a special
exception "XBREAK" that is caught by the TRY instruction,
which in turn implements the 'break' operation. The
problem is that this requires that the TRY instruction
is somehow told where to jump in this situation. (Any
cleaning up of stuff in the try/except block is handled
by the exception handling system, so no problem there.)
* It should be possible to disable, translate or completely
eliminate the compiler and VM error and warning messages.
It must be possible to send them to other places than
stdout or stderr.
* Make unspecified arguments writable! While this would be
pretty hard with the old system (there is simply no space
allocated for the argument!), the new argument stack
might make it more feasible.
* Tail calls! (Probably needs a separation of work and
argument passing memory; register frame + stack, or
something...)
* Quick "ignore exceptions" CALL instruction for compiling
"try f();" constructs.
* Some ideas for the threaded VM dispatcher:
* Aligned (cacheline, preferably) instruction entry
points + arithmetics, instead of the current LUT
of jump addresses.
* Maybe the argument stack isn't all that great an idea
anyway...? It adds the overhead of a stack "pointer" and
stack checking, but what does it buy us, really?
* What are we actually using VM LIST values for? They do have
lower overhead than any proper array object, but are they
actually used for anything that couldn't just be done by
passing a register start index and a register count instead?
(Remember; we have no hard limit on VM instruction size or
argument count...)
* More efficient solution for object initialization! It would
be nice if we could eliminate the intermediate "list of
registers" step, at least in some common cases...
* Move constants up to the module level, for less duplication.
Disadvantage: Larger contant indices in large modules... So,
use both module and function level constants? Use negative
indices for module level constants, to avoid any extra
logic/math beyond the sign test. However, this will require
some clever optimizer stage to figure out where each constant
should go.
* Maybe analyze the constant usage and try to fit a window of
256 elements or so over the most frequently used constants,
and use special small constant access instructions for those?
(Mostly a size optimization, probably, as getting that window
base index likely costs more than a larger index operand.)
EEL compiler
-----------------------------------------------------------
* Nicer peephole optimizer implementation. (A table that's
rendered into a 2D LUT or something at startup.)
* Should also deal with registers being unused as a
result of substituting "shortcut" instructions!
* Add more peephole optimizations! Any automatic tools
for finding safe or at least potential optimizations...?
* When encountering ANY compile error that involves some
known symbol where a name (from the lexer POV) is
expected, suggest that there is a naming conflict, and
identify the symbol found where the name was expected!
As it is, EEL can give some incredibly confusing
error messages due to trivial mistakes like these...