Future plans: * Globals (requires a separate mmaped segment in JIT compiler) * Function overloading: separate functions from values (again) in interpreter, allow casting to specific function type to take function value * Const propagation: annotate expression AST nodes that are computable in compile-time * Generic parameters: can be either values or `t : type`, but always compile-time * Generic structs: `struct array:`, require explicitly specifying parameters when instantiated (used as a type or creating a value) * Generic functions: `func max(a : t[n]):`, require explicitly specifying parameters when called or converted to function pointer * Generic parameter inference for functions & structs * Extension functions: operator overloading, destructors, iterators & for loop, move assignment (replaces built-in copy) * Metaprogramming: assigning types to variables (of type `type`), functions can take `type` as regular arguments and return `type`, all type computations are compile-time only Interpreter backlog: * Fix identifier resolution for functions & variables * Replace tree-walking interpreter with IR-based interpreter (invalidates the previous item) * C FFI (foreign functions) Aarch64 compiler backlog: (empty!) Optimizer plans: * Inlining: track function IR size (number of nodes will do), substitute its code instead of calling if it is small enough (pay attention to recursion) * Constant folding & propagation: if all node arguments are `const` nodes, replace the current node with the computed value * Arithmetic simplification: replace a+0 with a, etc (maybe also replace `var+const+const` with `var+const` for array/struct access) * Branch removal: `if` nodes with condition nodes being `const` are replaced with unconditional jumps * Jump removal: `jump` that jumps to the immediate successor node is removed * Dead code elimination: DFS from function `return` nodes & impure function calls, remove all nodes not visited (make sure to not remove function arguments) General backlog: * Mutually recursive structs (relevant only with pointers) * Empty array expression * Calling functions as methods * Replace std::runtime_error with appropriate custom exception types * Replace std::ostringstream with std::format (need support for std::format in type/ast printing) * TEST COVERAGE!!!