-
Notifications
You must be signed in to change notification settings - Fork 0
/
todo.txt
187 lines (163 loc) · 6.55 KB
/
todo.txt
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
---------------------
TODO:
---------------------
Final frontend changes
-Variable syntax should be changed to "name: type"
-StmtOrDecl is one of the most performance critical
parsing routines, and it currently uses backtracking
-Also is probably good for code readability in the long run
-Lambdas (types and exprs) as syntactic sugar for functype and func
Function type sugar in lambda form:
\ A,B -> D
instead of:
functype D(A,B)
Lambda expressions will be: \ A a, B b: expr
or: \ A a, B b {stmts...}
Alternately, with non-inferred
return type: \ A a, B b -> D: expr
\ A a, B b -> D {stmts...}
auto f1 = \(int a, float b): a * 10 - b;
auto f2 = \(int a, float b)
{
return a * 10 - b;
};
auto g1 = \(int a, float b) -> double: a * 5 - b * 3;
auto g2 = \(int a, float b) -> double
{
double c = a * 1.4;
return c * 5 - b * 3;
};
Pattern matching issues:
A call with union(s) as arguments will first match with overload taking the unions.
Otherwise, it matches the overload at runtime based on which type the union's underlying value is.
Functions returning error:
-Should not have to write overloads to handle error
-Make T? implicitly convertible to T, but if T is error at runtime:
* if in a subr that possibly returns error, return it
* otherwise, abort the whole program.
- For debug builds, should print a decent message and exit
- For release builds, assume this never happens
-A bit like exceptions but much simpler.
-Argument types just appear as a tuple type.
-Backslash immediately distinguishes
function types in parseType, so easy to parse
FRONTEND TESTING TODO:
-First-class functions
-First-class functions with overloads
-extern functions:
-Need to design memory ownership model for passing pointers
-Need to prevent leaks, use-after-free, double free
-Each argument can have one of several different modes:
-RELEASE: pass ownership to callee, memory no longer accessible and not responsible for freeing.
-For arrays, this means the value is replaced by []
-SHARE: Onyx keeps ownership and passes a non-const view.
-SHARE_CONST: Onyx keeps ownership and passes a const view.
-COPY: pass a deep copy
-Should work in interpreter!
-main libc functions will already be available to the compiler
-load other functions from dynamic library (?)
-Metaprogramming
-Implement "# StatementOrDecl" pattern to execute statements
at parse time, and create meta-declarations
-Implement all AST nodes as types
BACKEND
-IR rewrite:
-Remove "print" and "assert" as instructions - make them FFI calls
-Create parallel, simplified type system like LLVM
-All optimizations should work on the IR only - it should be possible to
completely delete the AST
-Metaprogramming:
-Put '#' before any pseudo-statement (scoped decls and regular statements)
-A scoped decl after # must be variable or subroutine
(all other scoped decls must exist in both meta world and regular program)
-Meta-variables are different kind of name than (normal scoping applies)
-Meta-subroutines can contain $/@-statements, regular ones can't
-they can still be represented as Subroutine, just add 'meta' bool
-Meta-statements are run at compile time (have no presense in final C/machine code output)
-#define <identifier> <tokens> works just like C
-meta-procs provide function-like macros
-Implicit conversion from string to any AST node type is parsing
-All meta-decls are resolved immediately after parsing
-This triggers lazy resolution of any needed decls in non-meta space
-If these decls are located earlier in the code, everything's fine
-Otherwise, it's an error (name doesn't exist yet)
-Meta built-in types and functions:
-Have capitalized names be types representing AST nodes
e.g. StringLit, For, Type, etc.
-Have lowercase names be functions that take a string
and parse it into an AST node
Example:
#Type t = type("float[][]");
-New syntax rules:
* (anywhere): #<stmt>: execute meta-stmt or create meta-decl
* (in meta-stmt): $<expr>: evaluate expr, unparse and output to code stream where the meta-stmt appeared
* Save "@" for potential later use in metaprogramming...
//This is a fully functional "include",
//although real compiler should have #include
//built in so that file/line/col works with multiple files
//also, should actually include each file once, even if #included
//multiple times
#proc void include(string fname)
{
string text = readFile(fname);
@text;
}
//C++ style generics (but with code size reduction option)
//need keyword "generic"
//example syntax:
generic(T)
func int serialSize(T val)
{
return serialize(val).len;
}
//compiler could implement by fully instantiating the decl for every type,
//or by creating a single decl that has a union that covers all uses
//suppose program uses:
serialSize(int)(6);
serialSize(string)("omgwtfbbq");
serialSize(byte[])([1, 2, 3, 4, 5]);
//there could be represented in final code by:
func int serialSize_int__(int val)
func int serialSize_string__(string val)
func int serialSize_byte_arr__(byte[] val)
//OR as:
//argument is implicitly converted to exact match in union,
//and if return value is a T union then extract the real value
func int serialSize((int | string | byte[]) val)
{
match v : val
{
case int:
return serialize(v).len;
case string:
return serialize(v).len;
case byte[]:
return serialize(v).len;
}
}
-----------------------------------
After core language compiler:
-----------------------------------
BUILT-IN MODULES (all must be fully cross-platform)
-Term (stdin/stdout/formatting/parsing, commands)
-Sys (File I/O, filesystem, sockets, time)
-GL (4.1+), plus some nice utilties, like:
-GLM-style math
-OBJ model loading
-Shader utilities
-Mesh utilities (half-edge structure, loading, saving)
-Font (Unicode support, antialiasing)
-Input (keyboard, mouse, gamepad - must be portable)
-Want to be able to poll keys/buttons efficiently like SDL,
or set callbacks for button events
-callbacks can be very simple with first-class subrs
-UI through Nuklear
-Native audio wrapper?
-set(T) in global, implemented as (T : void)
-Compression, for use with serialization: Zstd? (speed > compression)
-Graph
-Directed and not
-Dijkstra's algo for single source reachability/distance
-Kosaraju's algo for strongly connected components
-topological sort
-Prim's algo for MST