Safely mutating stack
#47
Labels
improvement
Similar to enhancement, but there is already code which addresses this that must be improved
stack
#47
The problem with
stack
is that most mutating or iterating words don't take its highly dynamic nature into account (to name a few:|slideRight
and friends,sum
,join
, etc.) Same thing withconts
, which also is highly dynamic (even more thanstack
), but use ofconts
is discouraged, and if you really do need to touch it, then you canshallowCopy
andresub
it yourself.But being able to inspect and change
stack
as if it was just a block is one of the "killer features" of Novika. Expressions like1 2 3 stack sum
arise naturally.Note that I did make some patches to
reduce
so it supportsstack
(making things like1 2 3 stack sum
leave6
as expected), but they explicitly allowedstack
, while we want to do that implicitly and relieve the burden of thinking about a weird use case like this.For example.
|slideRight
doesn't assume it's running in the same stack that it's iterating over, leading to undefined behavior:1 2 3 stack ||-> [ 1 + ]
dies weirdly instead of making the stack look like2 3 4
, as one would assume.To close this safety hole, we'd have to use some sort of instantiation or automatic split-join mechanism for stacks.
What I mean is that each stackless open (e.g.
... [ 1 + ] open
as well as[ 1 + ] @: foo ... foo
, i.e.,opens
) must make a snapshot of the stack it's being opened in, and use that stack. After it has been opened we must merge (join) its stack with the parent stack.The only difficulty here is actually finding the parent stack (i.e. preserving parent-child relationships for stacks). We can't simply join into the upper stack because of cases like this:
[ 1 2 ] [ + ] there
. Here, no merge must occur. A possible solution isnew
ing the stack inhydrate
(of whichthere
is a descendant), and making the stack instance an orphan. In case ofopen
and friends, we alsonew
the current stack, but this time the instance doesn't get orphan'd and thus gets a merge from the main loop, when the continuation is popped off.As a consequence, stackless opens become atomic (and
hydrate
s already are), meaning there is only two states: one before computation, and one after. Currently, in-between states are also accessible.Some minor thoughts:
conts ... shove
and derived expressions basically mean "f*ck off" to this whole mechanism.stack
still leaves legit current stack, not copy[ 1 2 3 ] ||-> [ 1 + ]
leaves[ 2 3 4 ]
, thus1 2 3 stack ||-> [ 1 + ]
should leave2 3 4 ⭮
, allowing for chains like1 2 3 stack ||-> [ 1 + ] map: [ 2 * ]
. The latter leaves2 3 4 ⭮
.⭮
and its contents,2 3 4
, are picked up bymap:
, leaving just[ 4 6 8 ]
on the stack (as[ 1 2 3 ] ||-> [ 1 + ] map: [ 2 * ]
already does.The text was updated successfully, but these errors were encountered: