https://gitlab.com/zsaleeba/picoc/-/blob/master/interpreter.h?ref_type=heads
kinda found how we can handle structs. the problems I have is how tf should I handle values in general, when to pass as a Value, when to allocate on stack, etc.
i think i lost the og interpreter “spec” where I describe how/when values should be copied.
I guess the new spec is:
by stack, i mean some sort of allocator (which can be a stack!). also can be an “expression stack”, meaning it’s only per expression!
one problem: when returing a value, it might still need to be on the stack, at least until the statement is finished.
// cond and any of its data needs to be kept...
const cond = try self.expr(ifs.cond);
if (isTrue(cond)) { // ...until here.
try self.stmts(ifs.bTrue);
} else {
// ...
notice, that we don’t correctly handle functions in structs yet. For now, I’m not planning on making struct sizes with functions in ‘em compatible.
In fact, down the line, I want to drop that compatibility in favor of explicitly marking them extern. That’s because in extern datatypes we should explicitly “mark” the environment (or its absence) of functions in structs.
IDEA: Maybe when we drop that compatibility and make structs not binary compatible by default, then we will correctly deallocate functions. (since we will be able to easily inspect them(? we can already do that doe)).
super slow. i’ve added a switch, so it’s not that slow. at least, normal expressions should not leak memory now. (right now, only EnvSnapshots put stuff in a global arena, because I still haven’t figured out how should I do the quick value passing)
a quick summary:
each statement creates a new expression stack and frees it at the end (this is done with ArenaAllocators)
also each scope (which, by scope, currently it means function scope) also creates its own ArenaAllocator, which gets freed at the end.
new handling for values: LValues and Owned (Smol and Stack), Smol is contained in the value itself, Stack is a reference to the stack (currently allocated by the stack arena allocator).
values contain size to not recalculate it constantly.;
ArenaAlloc option, which enables the previous allocation strategy (and disables deallocations)
result: i really gotta open a profiler now…
one good thing? we have a Value abstraction and a notion of ownership which I can change if need be (without modifying the calling code too much).