New games every week!
Stacking Up Blog
17th June 2025
On the subject of Stacks...
(In depth background JSE waffle ahead)

-=-=-

Have you looked into a call stack yet?
This would give you both local variables and a way to nest functions.


Pixel_Outlaw asked about using Call Stacks for a possible way to do Functions in JSE.

JSE works by taking what you've written, doing a BODMAS style sort on each line of code, shuffling things about a bit, and then writing a new form of parsed code that it can flick through nice and fast.



The parsed edition being ...
_f - Flush, new line.
String 1 is "Hello World"
Layer 1 - Part 0 : Use String 1 - Value is stored in slot 1,0
Layer 0 - Part 0 : Reference Layer 1 (which is just string 1) Value of 1,0 is copied to 0,0
Layer 0 - Part 1 : identifier "a" - The current value of a is stored in slot 0,1
Layer 0 - Part 2 : command "let" - The let command takes the name of the last identifier and assigns it the value currently stored in Part 0 of the current layer. So "variable[a]=0,0", which by this point is our string.

_f - Flush, new line.
Layer 1 - Part 0 : identifier "a" - the value of a (the string) is copied to slot 1,0
Layer 0 - Part 0 : Reference Layer 1, copying the string to slot 0,0
Layer 0 - Part 1 : Print, prints whatever's in slot 0,0

And this is a very simple bit of code, as you can obviously tell.
If you want to see this style of output, open the browser's DevConsole and type in JSE_Debug=2 before running a script.
Be warned that it gets VERY messy, though!

I should also note that everything has a numerical representation. The Print command, for example, is 13001.
The a variable will also be assigned a number, which I think is probably 53 or something, I can't remember where the user variables start. It doesn't matter, I coded it well enough to cope

Commands, references, layers, variables and more have all become numerical by this point, so all of those numbers are stored inside Int32Arrays. The only things left are the actual strings, which obviously have to be left as strings. (This is why there's that clunky bit where there's a string, then immediately a reference to that very same string)

But because everything's now just numbers, we can flick through essentially just a big array, really really fast.
And with a couple of year's of optimisation, I've got a whole bunch of little loops that the engine does in doublets and such, like if it sees a "Reference" as the next line, it'll quickly do that without starting the "interpreter" loop again.
There's the short loop, which deals with simple things like variables, maths, arrays, goto, if, and things like that, and then a longer loop which deals with actual commands.

If you want to see an example of the sort of slowdown the slower loop causes, you can run this script to see it in action.

start=Mills() for m=0 to 500000 a=a+1 next Print Mills()-start start=Mills() for m=0 to 500000 a=a+Int(1) next Print Mills()-start


So...
Back to the question.
Call Stacks.

Call Stacks are a nice way of thinking about this, but by the point we've got to, they're not exactly going to be easy to recognise as such
The Gosub functionality already accounts for stacks.
When a Gosub is used, the current "parsed" line number is stored in the stack, the line number is moved to the line requested, and then when the code hits the word Return, it jumps back to the previous line in the stack.
Adding "a return value" to this wouldn't be too hard, and assigning a few "take these values with you" things wouldn't either.

But...
And it's a big but...

Adding local variables would require assigning a new variable array, and/or clearing out that variable array when we jump back out again.
And you'd think that would be easy, but doing anything with assigning and freeing memory in Javascript is actually REALLY slow.

And I mean REALLY slow.

You know when you go online looking for Javascript examples, and it's always full of const assignments because const assignments are "optimised"
..
Are they bugger.
Shove that code into a hot-loop, and you'll be leaking memory like there's no tomorrow.
And then the GarbageCollect crops up, and slows everything back down again.
Gah!

The way JSE works is it pre-assigns all the necessary variable space during the parser, so that once it gets going, other than a few select commands which require it, like the Dim command, or the SetTilemapSize. Then there's no random new variables sprouting up, nor any clearing out of arrays unless absolutely necessary.
Because of this, local variables just aren't easy to handle. Or at the very least, I can't think of a good way to do it that won't cause masses of slowdown in the engine.

Like I said, the way that Functions would work would be very much like the Gosubs. I'll just need to shuffle things around a bit in the parsing stage, so that it'd go something like...

Print MyFunction(a)
becomes

StackedValueFromFunction[StackCount]=MyFunction(a)
Print StackedValueFromFunction[StackCount]

Or something to that effect. It "should" work ok, but like I say, if we start nesting those, it can get more than a little bit wobbly wobbly.
Views 157, Upvotes 1  
Daily Blog , Jse
New games every week!
Site credits : Jayenkai
(c) Jayenkai 2023 and onwards, RSS feed 5

Blog - Stacking Up - AGameAWeek